lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

Ruby.sublime-syntax (74439B)


      1 %YAML 1.2
      2 ---
      3 name: Ruby
      4 # TODO: unresolved issues
      5 #
      6 # text:
      7 # "p << end
      8 # print me!
      9 # end"
     10 # symptoms:
     11 # not recognized as a heredoc
     12 # solution:
     13 # there is no way to distinguish perfectly between the << operator and the start
     14 # of a heredoc. Currently, we require assignment to recognize a heredoc. More
     15 # refinement is possible.
     16 # • Heredocs with indented terminators (<<-) are always distinguishable, however.
     17 # • Nested heredocs are not really supportable at present
     18 #
     19 # text:
     20 # val?(a):p(b)
     21 # val?'a':'b'
     22 # symptoms:
     23 # ':p' is recognized as a symbol.. its 2 things ':' and 'p'.
     24 # :'b' has same problem.
     25 # solution:
     26 # ternary operator rule, precedence stuff, symbol rule.
     27 # but also consider 'a.b?(:c)' ??
     28 file_extensions:
     29   - rb
     30   - Appfile
     31   - Appraisals
     32   - Berksfile
     33   - Brewfile
     34   - capfile
     35   - cgi
     36   - Cheffile
     37   - config.ru
     38   - Deliverfile
     39   - Fastfile
     40   - fcgi
     41   - Gemfile
     42   - gemspec
     43   - Guardfile
     44   - irbrc
     45   - jbuilder
     46   - Podfile
     47   - podspec
     48   - prawn
     49   - pryrc
     50   - rabl
     51   - rake
     52   - Rakefile
     53   - Rantfile
     54   - rbx
     55   - rjs
     56   - ruby.rail
     57   - Scanfile
     58   - simplecov
     59   - Snapfile
     60   - thor
     61   - Thorfile
     62   - Vagrantfile
     63 first_line_match: |-
     64   (?xi:
     65     ^\#! .* \bj?ruby\b |                # shebang
     66     ^\# \s* -\*- [^*]* ruby [^*]* -\*-  # editorconfig
     67   )
     68 scope: source.ruby
     69 variables:
     70   bin_digits: (?:[01]+(?:_[01]+)*)
     71   dec_digits: (?:\d+(?:_\d+)*)
     72   hex_digits: (?:\h+(?:_\h+)*)
     73   oct_digits: (?:[0-7]+(?:_[0-7]+)*)
     74   dec_exponent: (?:[Ee][-+]?{{dec_digits}})
     75   heredoc_type_css: (?:[[:upper:]_]_)?CSS\b
     76   heredoc_type_html: (?:[[:upper:]_]_)?HTML\b
     77   heredoc_type_js: (?:[[:upper:]_]_)?(?:JS|JAVASCRIPT)\b
     78   heredoc_type_ruby: (?:[[:upper:]_]_)?RUBY\b
     79   heredoc_type_shell: (?:[[:upper:]_]_)?(?:SH|SHELL)\b
     80   heredoc_type_sql: (?:[[:upper:]_]_)?SQL\b
     81   identifier: '\b[[:alpha:]_][[:alnum:]_]*\b'
     82   method_punctuation: '(?:[?!]|=(?![>=]))?'
     83   method_name: '{{identifier}}{{method_punctuation}}'
     84   path_lookahead: '(::)?({{identifier}}(\.|::))*{{identifier}}'
     85 
     86 contexts:
     87   main:
     88     - include: expressions
     89 
     90   expressions:
     91     - include: constants
     92     - include: class
     93     - include: module
     94     - include: invalid
     95     - include: blocks
     96     - include: keywords
     97     - include: well-known-methods
     98     - include: variables
     99     - include: method
    100     - include: strings
    101     - include: comments
    102     - include: data-section
    103     - include: heredocs
    104     - include: punctuation
    105     - include: operators
    106     - include: identifiers-accessors
    107 
    108   comments:
    109     # multiline comments
    110     - match: ^=begin
    111       scope: punctuation.definition.comment.begin.ruby
    112       push:
    113         - meta_scope: comment.block.documentation.ruby
    114         - match: ^=end
    115           scope: punctuation.definition.comment.end.ruby
    116           pop: true
    117     - match: \#+
    118       scope: punctuation.definition.comment.ruby
    119       push:
    120         - meta_scope: comment.line.number-sign.ruby
    121         - match: \n
    122           pop: true
    123 
    124   class:
    125     # Defining a class method
    126     - match: \bclass\b(?=\s*<)
    127       scope: keyword.declaration.class.ruby
    128     - match: \bclass\b
    129       scope: keyword.declaration.class.ruby
    130       push: class-declaration
    131 
    132   class-declaration:
    133     - meta_scope: meta.class.ruby
    134     - match: '(?={{path_lookahead}})'
    135       set: class-name
    136     # Escape if no valid match
    137     - match: (?=\S)
    138       pop: true
    139 
    140   class-name:
    141     - meta_content_scope: meta.class.ruby entity.name.class.ruby
    142     - include: name-parts
    143     - match: ''
    144       set: class-inheritance
    145 
    146   class-inheritance:
    147     - meta_content_scope: meta.class.ruby
    148     - match: '<'
    149       scope: punctuation.separator.inheritance.ruby
    150       set:
    151         - meta_content_scope: meta.class.ruby
    152         - match: '(?={{path_lookahead}})'
    153           set:
    154             - meta_content_scope: meta.class.ruby entity.other.inherited-class.ruby
    155             - include: name-parts
    156             - match: ''
    157               pop: true
    158         # Escape if no valid match
    159         - match: '(?=\S)'
    160           pop: true
    161     # Escape if no valid match
    162     - match: '(?=\S)'
    163       pop: true
    164 
    165   module:
    166     - match: \bmodule\b
    167       scope: keyword.declaration.namespace.ruby
    168       push: module-declaration
    169 
    170   module-declaration:
    171     - meta_scope: meta.namespace.ruby
    172     - match: '(?=(::)?({{identifier}}::)*{{identifier}})'
    173       set:
    174         - meta_content_scope: meta.namespace.ruby entity.name.namespace.ruby
    175         - include: name-parts
    176         - match: ''
    177           pop: true
    178     # Escape if no valid match
    179     - match: (?=\S)
    180       pop: true
    181 
    182   name-parts:
    183     - match: ({{identifier}})?(?:(::)|(\.))
    184       captures:
    185         1: support.other.namespace.ruby
    186         2: punctuation.accessor.double-colon.ruby
    187         3: punctuation.accessor.dot.ruby
    188     - match: '{{identifier}}'
    189 
    190   invalid:
    191     # 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.
    192     - match: \belse\s+if\b
    193       scope: invalid.deprecated.ruby
    194 
    195   constants:
    196     # constant definition, handles multiple definitions on a single line 'APPLE, ORANGE= 1, 2'
    197     - match: '\b([[:upper:]]\w*)(?=(\s*,\s*[[:upper:]]\w*)*\s*=(?![=\>]))'
    198       scope: meta.constant.ruby entity.name.constant.ruby
    199     # Ruby 1.9 symbols
    200     - match: '{{identifier}}[?!]?(:)(?!:)'
    201       scope: constant.other.symbol.ruby
    202       captures:
    203         1: punctuation.definition.constant.ruby
    204       push: try-regex
    205     - match: '\b(nil|true|false)\b(?![?!])'
    206       scope: constant.language.ruby
    207     - match: '\b(__(FILE|LINE|ENCODING)__|self)\b(?![?!])'
    208       scope: variable.language.ruby
    209     # hexadecimal imaginary numbers: 0xAi, 0xAri
    210     - match: '\b(0[xX])({{hex_digits}})(r?i(r)?)\b'
    211       scope: meta.number.imaginary.hexadecimal.ruby
    212       captures:
    213         1: constant.numeric.base.ruby
    214         2: constant.numeric.value.ruby
    215         3: constant.numeric.suffix.ruby
    216         4: invalid.illegal.numeric.ruby
    217     # octal imaginary numbers: 0o1i, 0o1ri, 01i, 01ri
    218     - match: '\b(0[oO]?)({{oct_digits}})(r?i(r)?)\b'
    219       scope: meta.number.imaginary.octal.ruby
    220       captures:
    221         1: constant.numeric.base.ruby
    222         2: constant.numeric.value.ruby
    223         3: constant.numeric.suffix.ruby
    224         4: invalid.illegal.numeric.ruby
    225     # binary imaginary numbers: 0b1i, 0b1ri
    226     - match: '\b(0[bB])({{bin_digits}})(r?i(r)?)\b'
    227       scope: meta.number.imaginary.binary.ruby
    228       captures:
    229         1: constant.numeric.base.ruby
    230         2: constant.numeric.value.ruby
    231         3: constant.numeric.suffix.ruby
    232         4: invalid.illegal.numeric.ruby
    233     # decimal imaginary numbers: 0d1i, 0d1ri, 1i, 1ri, 1.1i, 1.1ri, 1e1i, 1.1e1i
    234     - match: |-
    235         \b(?x:
    236           (?:
    237             # 0d1i, 0d1ri, 1i, 1ri | 1.1i, 1.1ri
    238             (?: (0[dD])? ({{dec_digits}}) | ({{dec_digits}} (\.) {{dec_digits}}) ) (r?i)
    239             # 1e1i, 1.1e1i
    240             | ({{dec_digits}} (?: (\.) {{dec_digits}} )? {{dec_exponent}}) (r)?(i)
    241           ) (r)?
    242         )\b
    243       scope: meta.number.imaginary.decimal.ruby
    244       captures:
    245         1: constant.numeric.base.ruby
    246         2: constant.numeric.value.ruby
    247         3: constant.numeric.value.ruby
    248         4: punctuation.separator.decimal.ruby
    249         5: constant.numeric.suffix.ruby
    250         6: constant.numeric.value.ruby
    251         7: punctuation.separator.decimal.ruby
    252         8: constant.numeric.suffix.ruby invalid.illegal.numeric.ruby
    253         9: constant.numeric.suffix.ruby
    254         10: constant.numeric.suffix.ruby invalid.illegal.numeric.ruby
    255     # hexadecimal rational numbers: 0xAr
    256     - match: '\b(0[xX])({{hex_digits}})(r)\b'
    257       scope: meta.number.rational.hexadecimal.ruby
    258       captures:
    259         1: constant.numeric.base.ruby
    260         2: constant.numeric.value.ruby
    261         3: constant.numeric.suffix.ruby
    262     # octal rational numbers: 0o1r, 01r
    263     - match: '\b(0[oO]?)({{oct_digits}})(r)\b'
    264       scope: meta.number.rational.octal.ruby
    265       captures:
    266         1: constant.numeric.base.ruby
    267         2: constant.numeric.value.ruby
    268         3: constant.numeric.suffix.ruby
    269     # binary rational numbers: 0b1r
    270     - match: '\b(0[bB])({{bin_digits}})(r)\b'
    271       scope: meta.number.rational.binary.ruby
    272       captures:
    273         1: constant.numeric.base.ruby
    274         2: constant.numeric.value.ruby
    275         3: constant.numeric.suffix.ruby
    276     # decimal rational numbers: 0d1r, 1r, 1.1r
    277     - match: '\b(0[dD])?({{dec_digits}}|{{dec_digits}}(\.){{dec_digits}})(r)\b'
    278       scope: meta.number.rational.decimal.ruby
    279       captures:
    280         1: constant.numeric.base.ruby
    281         2: constant.numeric.value.ruby
    282         3: punctuation.separator.decimal.ruby
    283         4: constant.numeric.suffix.ruby
    284     # decimal floating point numbers: 1.1, 1e1, 1.1e1
    285     - match: '\b({{dec_digits}})(?:((\.){{dec_digits}})|((?:(\.){{dec_digits}})?{{dec_exponent}})(r)?)\b'
    286       scope: meta.number.float.decimal.ruby
    287       captures:
    288         1: constant.numeric.value.ruby
    289         2: constant.numeric.value.ruby
    290         3: punctuation.separator.decimal.ruby
    291         4: constant.numeric.value.ruby
    292         5: punctuation.separator.decimal.ruby
    293         6: constant.numeric.suffix.ruby invalid.illegal.numeric.rational.ruby
    294     # hexadecimal integer numbers: 0xA
    295     - match: '\b(0[xX])({{hex_digits}})\b'
    296       scope: meta.number.integer.hexadecimal.ruby
    297       captures:
    298         1: constant.numeric.base.ruby
    299         2: constant.numeric.value.ruby
    300     # octal integer numbers: 0o1, 01
    301     - match: '\b(0[oO]?)({{oct_digits}})\b'
    302       scope: meta.number.integer.octal.ruby
    303       captures:
    304         1: constant.numeric.base.ruby
    305         2: constant.numeric.value.ruby
    306     # binary integer numbers: 0b1
    307     - match: '\b(0[bB])({{bin_digits}})\b'
    308       scope: meta.number.integer.binary.ruby
    309       captures:
    310         1: constant.numeric.base.ruby
    311         2: constant.numeric.value.ruby
    312     # decimal integer numbers: 0d1, 1
    313     - match: '\b(0[dD])?({{dec_digits}})\b'
    314       scope: meta.number.integer.decimal.ruby
    315       captures:
    316         1: constant.numeric.base.ruby
    317         2: constant.numeric.value.ruby
    318     # Quoted symbols
    319     - match: ":'"
    320       scope: punctuation.definition.constant.ruby
    321       push:
    322         - meta_scope: meta.constant.ruby constant.other.symbol.single-quoted.ruby
    323         - match: "'"
    324           scope: punctuation.definition.constant.ruby
    325           pop: true
    326         - match: '\\[''\\]'
    327           scope: constant.character.escape.ruby
    328     - match: ':"'
    329       scope: punctuation.definition.constant.ruby
    330       push:
    331         - meta_scope: meta.constant.ruby constant.other.symbol.double-quoted.ruby
    332         - match: '"'
    333           scope: punctuation.definition.constant.ruby
    334           pop: true
    335         - include: interpolated-ruby
    336         - include: escaped-char
    337     # Unquoted symbols
    338     - match: |-
    339         (?x:
    340           (:)
    341           (
    342             {{identifier}}{{method_punctuation}}|
    343             ===?|
    344             >[>=]?|
    345             <[<=]?|
    346             <=>|
    347             [%&`/\|]|
    348             \*\*?|
    349             =?~|
    350             [-+]@?|
    351             \[\]=?|
    352             @@?{{identifier}}
    353           )
    354         )
    355       scope: constant.other.symbol.ruby
    356       captures:
    357         1: punctuation.definition.constant.ruby
    358     # questionmark literals
    359     - match: ((\?)\\u)(\{)
    360       captures:
    361         1: constant.character.ruby
    362         2: punctuation.definition.constant.ruby
    363         3: meta.braces.ruby punctuation.section.braces.begin.ruby
    364       push:
    365         - meta_scope: meta.constant.ruby
    366         - meta_content_scope: meta.braces.ruby
    367         - match: \}
    368           scope: meta.braces.ruby punctuation.section.braces.end.ruby
    369           pop: true
    370         - match: \h{0,6}
    371           scope: meta.number.integer.hexadecimal.ruby constant.numeric.value.ruby
    372         - match: \S
    373           scope: invalid.illegal.escape.ruby
    374     - match: |-
    375         (?x: (\?)(?:
    376           # examples (meta control sequences):
    377           # ?\C-a    ?\M-a    ?\M-\C-a    ?\ca    ?\M-ca
    378           (?:\\(?:[MC]-|c)){1,2}[[:ascii:]] |
    379           \\(?:
    380             # examples (hex):
    381             # ?\x1     ?\x61
    382             x\h{1,2}\b |
    383             # examples (octal):
    384             # ?\0      ?\07     ?\017
    385             0[0-7]{0,2}\b |
    386             # examples (escaped):
    387             # ?\n      ?\b      ?\\
    388             .(?!\w)
    389           ) |
    390           # examples (illegal):
    391           # ?abc     ?\xAG    ?\\n
    392           # ?_a0
    393           ([[:alpha:]_\\]\S+)\b(?!\s*:) |
    394           # examples (normal):
    395           # ?a       ?A       ?0
    396           # ?*       ?"       ?(
    397           # ?.       ?#       ?\
    398           [[:alnum:]_]\b(?!\s*:) | [^[:alnum:]_\s]
    399         ) )
    400       scope: constant.character.ruby
    401       captures:
    402         1: punctuation.definition.constant.ruby
    403         2: invalid.illegal.character.ruby
    404 
    405   blocks:
    406     - match: \bdo\b
    407       scope: keyword.control.block.do.ruby
    408       push: maybe-block-parameters
    409     - match: \{
    410       scope: punctuation.section.scope.ruby
    411       push: maybe-block-parameters
    412 
    413   maybe-block-parameters:
    414     - match: \|
    415       scope: meta.block.parameters.ruby punctuation.definition.parameters.begin.ruby
    416       set: block-parameters
    417     - match: (?=\s*[^\s\|])
    418       pop: true
    419 
    420   block-parameters:
    421     - meta_content_scope: meta.block.parameters.ruby
    422     - match: \|
    423       scope: meta.block.parameters.ruby punctuation.definition.parameters.end.ruby
    424       set: try-regex
    425     - match: '{{identifier}}'
    426       scope: variable.parameter.ruby
    427     - match: ','
    428       scope: punctuation.separator.ruby
    429     - match: \*
    430       scope: keyword.operator.splat.ruby
    431     - match: '&'
    432       scope: keyword.operator.ruby
    433     - match: '(?==)'
    434       set:
    435         - meta_content_scope: meta.block.parameters.default-value.ruby
    436         - match: '='
    437           scope: keyword.operator.assignment.ruby
    438           set:
    439             - meta_content_scope: meta.block.parameters.default-value.ruby
    440             - match: '(?=[,\|])'
    441               set: block-parameters
    442             - include: nest-all
    443             - include: expressions
    444 
    445   keywords:
    446     # blocks
    447     - match: \bbegin\b(?![?!])
    448       scope: keyword.control.block.begin.ruby
    449       push: after-keyword
    450     - match: \bend\b(?![?!])
    451       scope: keyword.control.block.end.ruby
    452     # conditional
    453     - match: \bcase\b(?![?!])
    454       scope: keyword.control.conditional.case.ruby
    455       push: after-keyword
    456     - match: \belse\b(?![?!])
    457       scope: keyword.control.conditional.if.ruby
    458       push: after-keyword
    459     - match: \belsif\b(?![?!])
    460       scope: keyword.control.conditional.elseif.ruby
    461       push: after-keyword
    462     - match: \bif\b(?![?!])
    463       scope: keyword.control.conditional.if.ruby
    464       push: after-keyword
    465     - match: \bthen\b(?![?!])
    466       scope: keyword.control.conditional.then.ruby
    467     - match: \bunless\b(?![?!])
    468       scope: keyword.control.conditional.unless.ruby
    469       push: after-keyword
    470     - match: \bwhen\b(?![?!])
    471       scope: keyword.control.conditional.when.ruby
    472       push: after-keyword
    473     # exception
    474     - match: \bensure\b(?![?!])
    475       scope: keyword.control.exception.ensure.ruby
    476       push: after-keyword
    477     - match: \brescue\b(?![?!])
    478       scope: keyword.control.exception.rescue.ruby
    479       push: after-keyword
    480     # loop
    481     - match: \bfor\b(?![?!])
    482       scope: keyword.control.loop.for.ruby
    483       push: after-keyword
    484     - match: \buntil\b(?![?!])
    485       scope: keyword.control.loop.until.ruby
    486       push: after-keyword
    487     - match: \bwhile\b(?![?!])
    488       scope: keyword.control.loop.while.ruby
    489       push: after-keyword
    490     # flow
    491     - match: \bbreak\b(?![?!])
    492       scope: keyword.control.flow.break.ruby
    493     - match: \bnext\b(?![?!])
    494       scope: keyword.control.flow.next.ruby
    495     - match: \bredo\b(?![?!])
    496       scope: keyword.control.flow.redo.ruby
    497     - match: \bretry\b(?![?!])
    498       scope: keyword.control.flow.retry.ruby
    499     - match: \breturn\b(?![?!])
    500       scope: keyword.control.flow.return.ruby
    501     - match: \byield\b(?![?!])
    502       scope: keyword.control.flow.yield.ruby
    503     # declarations
    504     - match: \b(?:alias|alias_method)\b(?![?!])
    505       scope: keyword.declaration.alias.ruby
    506       push: after-keyword
    507     - match: \bundef\b(?![?!])
    508       scope: keyword.declaration.undef.ruby
    509       push: after-keyword
    510     # operators
    511     - match: \b(?:and|not|or)\b
    512       scope: keyword.operator.logical.ruby
    513       push: after-keyword
    514     - match: \bin\b(?![?!])
    515       scope: keyword.operator.logical.ruby
    516       push: after-keyword
    517     # other functions
    518     - match: \b(?:BEGIN|END)\b(?![?!])
    519       scope: entity.name.function.prepocessor.ruby
    520     - match: \b(?:defined|block_given)\?
    521       scope: support.function.builtin.ruby
    522       push: after-keyword
    523     - match: \bsuper\b(?![?!])
    524       scope: support.function.builtin.ruby
    525       push: after-keyword
    526 
    527   operators:
    528     - match: '>>'
    529       scope: keyword.operator.other.ruby
    530       push: after-operator
    531     # note: `/=` is matched in the `regexes` context
    532     - match: <<=|&&=|\|\|=|\*\*=|[-+*&|^]=|<<
    533       scope: keyword.operator.assignment.augmented.ruby
    534       push: after-operator
    535     - match: <=>|===|<=|>=|==|=~|!=|!~|<|>
    536       scope: keyword.operator.comparison.ruby
    537       push: after-operator
    538     - match: \*\*|[-+*/%]
    539       scope: keyword.operator.arithmetic.ruby
    540       push: after-operator
    541     - match: =
    542       scope: keyword.operator.assignment.ruby
    543       push: after-operator
    544     - match: '!+|&&|\|\|'
    545       scope: keyword.operator.logical.ruby
    546       push: after-operator
    547     - match: '[~&|^]'
    548       scope: keyword.operator.bitwise.ruby
    549       push: after-operator
    550     - match: \?
    551       scope: keyword.operator.conditional.ruby
    552       push:
    553         # Handle hash-key-lookalike of identifier: in ternary
    554         - match: \s*{{identifier}}(:)(?!:)
    555           captures:
    556             1: keyword.operator.conditional.ruby
    557           set: after-operator
    558         - include: after-operator
    559     - match: :(?!:)
    560       scope: keyword.operator.conditional.ruby
    561       push: after-operator
    562     - match: \.\.\.?
    563       scope: keyword.operator.range.ruby
    564       push: after-operator
    565 
    566   punctuation:
    567     - match: =>
    568       scope: punctuation.separator.key-value.ruby
    569       push: after-operator
    570     - match: ','
    571       scope: punctuation.separator.sequence.ruby
    572       push: after-operator
    573     - match: ;
    574       scope: punctuation.terminator.statement.ruby
    575       push: after-operator
    576     - match: \[
    577       scope: punctuation.section.array.ruby
    578       push: after-operator
    579     - match: \(
    580       scope: punctuation.definition.group.begin.ruby
    581       push: after-operator
    582     # Opening { is handled by "block" context to try and detect parameters
    583     - match: \}
    584       scope: punctuation.section.scope.ruby
    585     - match: \]
    586       scope: punctuation.section.array.ruby
    587     - match: \)
    588       scope: punctuation.definition.group.end.ruby
    589 
    590   identifiers-accessors:
    591     # This consumes class/module access to prevent issues parsing : as part
    592     # of a ternary operator
    593     - match: ::(?={{identifier}}{{method_punctuation}})
    594       scope: punctuation.accessor.double-colon.ruby
    595       push:
    596         - include: well-known-methods
    597         - match: '{{identifier}}{{method_punctuation}}'
    598         - match: ''
    599           set: after-identifier
    600     # This consumes attribute access so we don't need a lookbehind for .
    601     - match: \.(?={{identifier}}{{method_punctuation}})
    602       scope: punctuation.accessor.dot.ruby
    603       push:
    604         - include: well-known-methods
    605         - match: '{{identifier}}{{method_punctuation}}'
    606         - match: ''
    607           set: after-identifier
    608     # This consumes method names ending in punctuation so we don't need a lookbehind for ?, ! or =
    609     - match: '{{identifier}}{{method_punctuation}}'
    610     # This consumes module/class accessor so we don't need a lookbehind for ::
    611       push: after-identifier
    612     - match: \.
    613       scope: punctuation.accessor.dot.ruby
    614     - match: '::'
    615       scope: punctuation.accessor.double-colon.ruby
    616 
    617   after-identifier:
    618     # Handles a : right after an identifier. In this case it can't be the
    619     # beginning of a symbol, so it must be part of a ternary operator
    620     - match: ':(?!:)'
    621       scope: keyword.operator.conditional.ruby
    622       pop: true
    623     - match: ''
    624       pop: true
    625 
    626   variables:
    627     - match: '(@)[a-zA-Z_]\w*'
    628       scope: variable.other.readwrite.instance.ruby
    629       captures:
    630         1: punctuation.definition.variable.ruby
    631     - match: '(@@)[a-zA-Z_]\w*'
    632       scope: variable.other.readwrite.class.ruby
    633       captures:
    634         1: punctuation.definition.variable.ruby
    635     - match: '(\$)[a-zA-Z_]\w*'
    636       scope: variable.other.readwrite.global.ruby
    637       captures:
    638         1: punctuation.definition.variable.ruby
    639     - match: '(\$)(!|@|&|`|''|\+|\d+|~|=|/|\\|,|;|\.|<|>|_|\*|\$|\?|:|"|-[0adFiIlpv])'
    640       scope: variable.other.readwrite.global.pre-defined.ruby
    641       captures:
    642         1: punctuation.definition.variable.ruby
    643     - match: '\b(ENV)\['
    644       captures:
    645         1: variable.other.constant.ruby
    646       push:
    647         - meta_scope: meta.environment-variable.ruby
    648         - match: '\]'
    649           pop: true
    650         - include: expressions
    651     - match: '(::)?(\b[[:upper:]]\w*)(?=((\.|::)[[:alpha:]_]|\[))'
    652       captures:
    653         1: punctuation.accessor.double-colon.ruby
    654         2: support.class.ruby
    655     - match: '\b[[:upper:]]\w*\b'
    656       scope: variable.other.constant.ruby
    657 
    658   well-known-methods:
    659     # exceptions
    660     - match: \bcatch\b(?![?!])
    661       scope: keyword.control.exception.catch.ruby
    662       push: function-call-arguments
    663     # flow
    664     - match: \b(?:fail|raise|throw)\b(?![?!])
    665       scope: keyword.control.flow.throw.ruby
    666       push: function-call-arguments
    667     # loop
    668     - match: \bloop\b(?![?!])
    669       scope: keyword.control.loop.loop.ruby
    670       push: function-call-arguments
    671     # other
    672     - match: \b(initialize|new|include|extend|prepend|attr_reader|attr_writer|attr_accessor|attr|module_function|public|protected|private)\b(?![?!])
    673       scope: keyword.other.special-method.ruby
    674       push: function-call-arguments
    675     - match: \b(require|require_relative|gem)\b
    676       scope: keyword.control.import.ruby
    677       push:
    678         - meta_scope: meta.require.ruby
    679         - match: $|(?=[#}])
    680           pop: true
    681         - include: expressions
    682     # Conversion methods
    683     - match: |-
    684         (?x:
    685           \b(
    686             to_ary|
    687             to_a|
    688             to_c|
    689             to_enum|
    690             to_f|
    691             to_hash|
    692             to_h|
    693             to_int|
    694             to_io|
    695             to_i|
    696             to_proc|
    697             to_r|
    698             to_str|
    699             to_sym|
    700             to_s
    701           )\b
    702           (?![!?=])
    703         )
    704       scope: support.function.builtin.ruby
    705       push: function-call-arguments
    706     # Methods that may be followed by a regex
    707     - match: |-
    708         (?x:
    709           \b(
    710             gsub|
    711             sub
    712           )(!|\b)
    713           |
    714           \b(
    715             match
    716           )(\?|\b)
    717           |
    718           \b(
    719             assert_match|
    720             assert_no_match|
    721             index|
    722             rindex|
    723             scan
    724           )\b(?![!?=])
    725         )
    726       scope: support.function.builtin.ruby
    727       push: function-call-arguments
    728     # Methods from the Object class not handled elsewhere, ending in punctuation
    729     - match: |-
    730         (?x:
    731           \b(
    732             eql\?|
    733             instance_of\?|
    734             instance_variable_defined\?|
    735             is_a\?|
    736             kind_of\?|
    737             nil\?|
    738             respond_to\?|
    739             respond_to_missing\?|
    740             tainted\?|
    741             untrusted\?
    742           )
    743         )
    744       scope: support.function.builtin.ruby
    745       push: function-call-arguments
    746     # Methods from the Object class not handled elsewhere
    747     - match: |-
    748         (?x:
    749           \b(
    750             class|
    751             clone|
    752             define_singleton_method|
    753             display|
    754             dup|
    755             enum_for|
    756             extend|
    757             freeze|
    758             frozen?|
    759             hash|
    760             inspect|
    761             instance_variable_get|
    762             instance_variable_set|
    763             instance_variables|
    764             itself|
    765             method|
    766             methods|
    767             object_id|
    768             private_methods|
    769             protected_methods|
    770             public_method|
    771             public_methods|
    772             public_send|
    773             remove_instance_variable|
    774             send|
    775             singleton_class|
    776             singleton_method|
    777             singleton_methods|
    778             taint|
    779             tap|
    780             trust|
    781             untaint|
    782             untrust
    783           )\b
    784           (?![!?=])
    785         )
    786       scope: support.function.builtin.ruby
    787       push: function-call-arguments
    788     # Methods from the Kernel class not handled elsewhere, ending in punctuation
    789     - match: |-
    790         (?x:
    791           \b(
    792             autoload\?|
    793             iterator\?|
    794             exit!
    795           )
    796         )
    797       scope: support.function.builtin.ruby
    798       push: function-call-arguments
    799     # Methods from the Kernel class not handled elsewhere
    800     - match: |-
    801         (?x:
    802           \b(
    803             Array|
    804             Complex|
    805             Float|
    806             Hash|
    807             Integer|
    808             Rational|
    809             String|
    810             __callee__|
    811             __dir__|
    812             __method__|
    813             abort|
    814             at_exit|
    815             autoload|
    816             binding|
    817             callcc|
    818             caller|
    819             caller_locations|
    820             chomp|
    821             chop|
    822             eval|
    823             exec|
    824             exit|
    825             fork|
    826             format|
    827             gets|
    828             global_variables|
    829             gsub|
    830             lambda|
    831             load|
    832             local_variables|
    833             open|
    834             p|
    835             print|
    836             printf|
    837             proc|
    838             putc|
    839             puts|
    840             rand|
    841             readline|
    842             readlines|
    843             require|
    844             require_relative|
    845             select|
    846             set_trace_func|
    847             sleep|
    848             spawn|
    849             sprintf|
    850             srand|
    851             sub|
    852             syscall|
    853             system|
    854             test|
    855             trace_var|
    856             trap|
    857             untrace_var|
    858             warn
    859           )\b
    860           (?![!?=])
    861         )
    862       scope: support.function.builtin.ruby
    863       push: function-call-arguments
    864     # Methods from the Kernel class not handled elsewhere, ending in punctuation
    865     - match: |-
    866         (?x:
    867           \b(
    868             class_variable_defined\?|
    869             const_defined\?|
    870             include\?|
    871             instance_methods\?|
    872             method_defined\?|
    873             private_method_defined\?|
    874             protected_method_defined\?|
    875             public_method_defined\?|
    876             singleton_class\?
    877           )
    878         )
    879       scope: support.function.builtin.ruby
    880       push: function-call-arguments
    881     # Lambda operator from the Kernel class not handled elsewhere
    882     - match: '->'
    883       scope: meta.function.ruby keyword.declaration.function.anonymous.ruby
    884       push: function-call-arguments
    885     # Methods from the Module class not handled elsewhere
    886     - match: |-
    887         (?x:
    888           \b(
    889             ancestors|
    890             append_features|
    891             class_eval|
    892             class_exec|
    893             class_variable_get|
    894             class_variable_set|
    895             class_variables|
    896             const_get|
    897             const_missing|
    898             const_set|
    899             constants|
    900             define_method|
    901             extend_object|
    902             extended|
    903             freeze|
    904             included|
    905             included_modules|
    906             inspect|
    907             method_added|
    908             method_removed|
    909             method_undefined|
    910             module_eval|
    911             module_exec|
    912             name|
    913             prepend_features|
    914             prepended|
    915             private_class_method|
    916             private_constant|
    917             private_instance_methods|
    918             protected_instance_methods|
    919             public_class_method|
    920             public_constant|
    921             public_instance_method|
    922             public_instance_methods|
    923             refine|
    924             remove_class_variable|
    925             remove_const|
    926             remove_method|
    927             undef_method|
    928             using
    929           )\b
    930           (?![!?=])
    931         )
    932       scope: support.function.builtin.ruby
    933       push: function-call-arguments
    934 
    935   function-call-arguments:
    936     - include: try-regex
    937 
    938   method:
    939     - match: \bdef\b
    940       scope: meta.function.ruby keyword.declaration.function.ruby
    941       push:
    942         - meta_content_scope: meta.function.ruby
    943         - match: '(self)(\.)({{identifier}}{{method_punctuation}}|===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?)'
    944           captures:
    945             1: variable.language.ruby
    946             2: punctuation.accessor.dot.ruby
    947             3: entity.name.function.ruby
    948           set: method-parameters-start
    949         - match: '===?|>[>=]?|<=>|<[<=]?|[%&`/\|]|\*\*?|=?~|[-+]@?|\[\]=?'
    950           scope: entity.name.function.ruby
    951           set: method-parameters-start
    952         - match: '(?:({{identifier}})(?:(::)|(\.)))?{{identifier}}{{method_punctuation}}'
    953           scope: entity.name.function.ruby
    954           captures:
    955             1: support.other.namespace.ruby
    956             2: punctuation.accessor.double-colon.ruby
    957             3: punctuation.accessor.dot.ruby
    958           set: method-parameters-start
    959         - match: '$'
    960           pop: true
    961         - match: '(?=\S)'
    962           pop: true
    963 
    964   method-parameters-start:
    965     - meta_content_scope: meta.function.ruby
    966     - match: '(?=\()'
    967       set:
    968         - meta_content_scope: meta.function.parameters.ruby
    969         - match: '\('
    970           scope: punctuation.definition.group.begin.ruby
    971           set: method-parameters
    972     # No parameters
    973     - match: '(?=$|;|#)'
    974       pop: true
    975     # No parentheses around parameters
    976     - match: '(?=[[:alpha:]_*])'
    977       set: method-bare-parameters
    978 
    979   method-parameters:
    980     - meta_content_scope: meta.function.parameters.ruby
    981     - match: '\)'
    982       scope: meta.function.parameters.ruby punctuation.definition.group.end.ruby
    983       pop: true
    984     - match: '{{identifier}}'
    985       scope: variable.parameter.ruby
    986     - include: comments
    987     - match: ','
    988       scope: punctuation.separator.ruby
    989     - match: '\*'
    990       scope: keyword.operator.splat.ruby
    991     - match: '&'
    992       scope: keyword.operator.ruby
    993     # De-structuring
    994     - match: \(
    995       scope: punctuation.definition.group.begin.ruby
    996       push:
    997         - match: \)
    998           scope: punctuation.definition.group.end.ruby
    999           pop: true
   1000         - match: '{{identifier}}'
   1001           scope: variable.parameter.ruby
   1002         - match: ','
   1003           scope: punctuation.separator.ruby
   1004         - match: '\*'
   1005           scope: keyword.operator.splat.ruby
   1006     # Default values
   1007     - match: (?==)
   1008       set:
   1009         - meta_content_scope: meta.function.parameters.default-value.ruby
   1010         - match: '='
   1011           scope: keyword.operator.assignment.ruby
   1012           set:
   1013             - meta_content_scope: meta.function.parameters.default-value.ruby
   1014             - match: '(?=[,\)])'
   1015               set: method-parameters
   1016             - include: nest-all
   1017             - include: expressions
   1018     # Keyword parameter (with default value support)
   1019     - match: (?=:)
   1020       set:
   1021         - meta_content_scope: meta.function.parameters.default-value.ruby
   1022         - match: ':'
   1023           scope: punctuation.separator.ruby
   1024           set:
   1025             - meta_content_scope: meta.function.parameters.default-value.ruby
   1026             - match: '(?=[,\)])'
   1027               set: method-parameters
   1028             - include: nest-all
   1029             - include: expressions
   1030 
   1031   # When no parentheses are placed around the parameters
   1032   method-bare-parameters:
   1033     - meta_content_scope: meta.function.parameters.ruby
   1034     - match: '(?=$|;|#)'
   1035       pop: true
   1036     - match: '{{identifier}}'
   1037       scope: variable.parameter.ruby
   1038     - match: ','
   1039       scope: punctuation.separator.ruby
   1040     - match: '\*'
   1041       scope: keyword.operator.splat.ruby
   1042     - match: '&'
   1043       scope: keyword.operator.ruby
   1044     # Default values
   1045     - match: (?==)
   1046       set:
   1047         - meta_content_scope: meta.function.parameters.default-value.ruby
   1048         - match: '='
   1049           scope: punctuation.operator.assignment.ruby
   1050           set:
   1051             - meta_content_scope: meta.function.parameters.default-value.ruby
   1052             - match: '(?=$|[,;])'
   1053               set: method-bare-parameters
   1054             - include: nest-all
   1055             - include: expressions
   1056     # Keyword parameter (with default value support)
   1057     - match: (?=:)
   1058       set:
   1059         - meta_content_scope: meta.function.parameters.default-value.ruby
   1060         - match: ':'
   1061           scope: punctuation.separator.ruby
   1062           set:
   1063             - meta_content_scope: meta.function.parameters.default-value.ruby
   1064             - match: '(?=$|[,;])'
   1065               set: method-bare-parameters
   1066             - include: nest-all
   1067             - include: expressions
   1068 
   1069   strings:
   1070     - include: early-strings
   1071     - include: regexes
   1072     - include: late-strings
   1073 
   1074   early-strings:
   1075     # single quoted string (does not allow interpolation)
   1076     - match: "'"
   1077       scope: punctuation.definition.string.begin.ruby
   1078       push:
   1079         - meta_scope: meta.string.ruby string.quoted.single.ruby
   1080         - match: "'"
   1081           scope: punctuation.definition.string.end.ruby
   1082           pop: true
   1083         - match: \\'|\\\\
   1084           scope: constant.character.escape.ruby
   1085         - include: string-placeholder
   1086     # double quoted string (allows for interpolation)
   1087     - match: '"'
   1088       scope: punctuation.definition.string.begin.ruby
   1089       push:
   1090         - meta_scope: meta.string.ruby string.quoted.double.ruby
   1091         - match: '"'
   1092           scope: punctuation.definition.string.end.ruby
   1093           pop: true
   1094         - include: interpolated-ruby
   1095         - include: escaped-char
   1096         - include: string-placeholder
   1097     # execute string (allows for interpolation)
   1098     - match: "`"
   1099       scope: punctuation.definition.string.begin.ruby
   1100       push:
   1101         - meta_scope: meta.string.ruby string.interpolated.ruby
   1102         - match: "`"
   1103           scope: punctuation.definition.string.end.ruby
   1104           pop: true
   1105         - include: interpolated-ruby
   1106         - include: escaped-char
   1107     # execute string (allow for interpolation)
   1108     - match: '%x\{'
   1109       scope: punctuation.definition.string.begin.ruby
   1110       push:
   1111         - meta_scope: meta.string.ruby string.interpolated.ruby
   1112         - match: '\}'
   1113           scope: punctuation.definition.string.end.ruby
   1114           pop: true
   1115         - include: interpolated-ruby
   1116         - include: escaped-char
   1117         - include: nest-curly-i
   1118     # execute string (allow for interpolation)
   1119     - match: '%x\['
   1120       scope: punctuation.definition.string.begin.ruby
   1121       push:
   1122         - meta_scope: meta.string.ruby string.interpolated.ruby
   1123         - match: '\]'
   1124           scope: punctuation.definition.string.end.ruby
   1125           pop: true
   1126         - include: interpolated-ruby
   1127         - include: escaped-char
   1128         - include: nest-brackets-i
   1129     # execute string (allow for interpolation)
   1130     - match: '%x\<'
   1131       scope: punctuation.definition.string.begin.ruby
   1132       push:
   1133         - meta_scope: meta.string.ruby string.interpolated.ruby
   1134         - match: \>
   1135           scope: punctuation.definition.string.end.ruby
   1136           pop: true
   1137         - include: interpolated-ruby
   1138         - include: escaped-char
   1139         - include: nest-ltgt-i
   1140     # execute string (allow for interpolation)
   1141     - match: '%x\('
   1142       scope: punctuation.definition.string.begin.ruby
   1143       push:
   1144         - meta_scope: meta.string.ruby string.interpolated.ruby
   1145         - match: \)
   1146           scope: punctuation.definition.string.end.ruby
   1147           pop: true
   1148         - include: interpolated-ruby
   1149         - include: escaped-char
   1150         - include: nest-parens-i
   1151     # execute string (allow for interpolation)
   1152     - match: '%x([^\w])'
   1153       scope: punctuation.definition.string.begin.ruby
   1154       push:
   1155         - meta_scope: meta.string.ruby string.interpolated.ruby
   1156         - match: \1
   1157           scope: punctuation.definition.string.end.ruby
   1158           pop: true
   1159         - include: interpolated-ruby
   1160         - include: escaped-char
   1161 
   1162   late-strings:
   1163     # literal capable of interpolation ()
   1164     - match: '%[QW]?\('
   1165       scope: punctuation.definition.string.begin.ruby
   1166       push:
   1167         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1168         - match: \)
   1169           scope: punctuation.definition.string.end.ruby
   1170           pop: true
   1171         - include: interpolated-ruby
   1172         - include: escaped-char
   1173         - include: nest-parens-i
   1174     # "literal capable of interpolation []"
   1175     - match: '%[QW]?\['
   1176       scope: punctuation.definition.string.begin.ruby
   1177       push:
   1178         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1179         - match: '\]'
   1180           scope: punctuation.definition.string.end.ruby
   1181           pop: true
   1182         - include: interpolated-ruby
   1183         - include: escaped-char
   1184         - include: nest-brackets-i
   1185     # literal capable of interpolation <>
   1186     - match: '%[QW]?\<'
   1187       scope: punctuation.definition.string.begin.ruby
   1188       push:
   1189         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1190         - match: \>
   1191           scope: punctuation.definition.string.end.ruby
   1192           pop: true
   1193         - include: interpolated-ruby
   1194         - include: escaped-char
   1195         - include: nest-ltgt-i
   1196     # literal capable of interpolation -- {}
   1197     - match: '%[QW]?\{'
   1198       scope: punctuation.definition.string.begin.ruby
   1199       push:
   1200         - meta_scope: meta.string.ruby string.quoted.double.ruby.mod
   1201         - match: '\}'
   1202           scope: punctuation.definition.string.end.ruby
   1203           pop: true
   1204         - include: interpolated-ruby
   1205         - include: escaped-char
   1206         - include: nest-curly-i
   1207     # literal capable of interpolation -- wildcard
   1208     - match: '%[QW]([^\w])'
   1209       scope: punctuation.definition.string.begin.ruby
   1210       push:
   1211         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1212         - match: \1
   1213           scope: punctuation.definition.string.end.ruby
   1214           pop: true
   1215         - include: interpolated-ruby
   1216         - include: escaped-char
   1217     # literal capable of interpolation -- wildcard
   1218     - match: '%([^\w\s=])'
   1219       scope: punctuation.definition.string.begin.ruby
   1220       push:
   1221         - meta_scope: meta.string.ruby string.quoted.other.literal.other.ruby
   1222         - match: \1
   1223           scope: punctuation.definition.string.end.ruby
   1224           pop: true
   1225         - include: interpolated-ruby
   1226         - include: escaped-char
   1227     # literal capable of interpolation ()
   1228     - match: '%I\('
   1229       scope: punctuation.definition.string.begin.ruby
   1230       push:
   1231         - match: '\w+'
   1232           scope: constant.other.symbol.ruby
   1233         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1234         - match: \)
   1235           scope: punctuation.definition.string.end.ruby
   1236           pop: true
   1237         - include: interpolated-ruby
   1238         - include: escaped-char
   1239         - include: nest-parens-i
   1240     # "literal capable of interpolation []"
   1241     - match: '%I\['
   1242       scope: punctuation.definition.string.begin.ruby
   1243       push:
   1244         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1245         - match: '\w+'
   1246           scope: constant.other.symbol.ruby
   1247         - match: '\]'
   1248           scope: punctuation.definition.string.end.ruby
   1249           pop: true
   1250         - include: interpolated-ruby
   1251         - include: escaped-char
   1252         - include: nest-brackets-i
   1253     # literal capable of interpolation <>
   1254     - match: '%I\<'
   1255       scope: punctuation.definition.string.begin.ruby
   1256       push:
   1257         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1258         - match: '\w+'
   1259           scope: constant.other.symbol.ruby
   1260         - match: \>
   1261           scope: punctuation.definition.string.end.ruby
   1262           pop: true
   1263         - include: interpolated-ruby
   1264         - include: escaped-char
   1265         - include: nest-ltgt-i
   1266     # literal capable of interpolation -- {}
   1267     - match: '%I\{'
   1268       scope: punctuation.definition.string.begin.ruby
   1269       push:
   1270         - meta_scope: meta.string.ruby string.quoted.double.ruby.mod
   1271         - match: '\w+'
   1272           scope: constant.other.symbol.ruby
   1273         - match: '\}'
   1274           scope: punctuation.definition.string.end.ruby
   1275           pop: true
   1276         - include: interpolated-ruby
   1277         - include: escaped-char
   1278         - include: nest-curly-i
   1279     # literal capable of interpolation -- wildcard
   1280     - match: '%I([^\w])'
   1281       scope: punctuation.definition.string.begin.ruby
   1282       push:
   1283         - meta_scope: meta.string.ruby string.quoted.other.literal.upper.ruby
   1284         - match: '\w+'
   1285           scope: constant.other.symbol.ruby
   1286         - match: \1
   1287           scope: punctuation.definition.string.end.ruby
   1288           pop: true
   1289         - include: interpolated-ruby
   1290         - include: escaped-char
   1291     # literal incapable of interpolation -- ()
   1292     - match: '%[qws]\('
   1293       scope: punctuation.definition.string.begin.ruby
   1294       push:
   1295         - meta_scope: meta.string.ruby string.quoted.other.literal.lower.ruby
   1296         - match: \)
   1297           scope: punctuation.definition.string.end.ruby
   1298           pop: true
   1299         - match: \\\)|\\\\
   1300           scope: constant.character.escape.ruby
   1301         - include: nest-parens
   1302     # literal incapable of interpolation -- <>
   1303     - match: '%[qws]\<'
   1304       scope: punctuation.definition.string.begin.ruby
   1305       push:
   1306         - meta_scope: meta.string.ruby string.quoted.other.literal.lower.ruby
   1307         - match: \>
   1308           scope: punctuation.definition.string.end.ruby
   1309           pop: true
   1310         - match: \\\>|\\\\
   1311           scope: constant.character.escape.ruby
   1312         - include: nest-ltgt
   1313     # literal incapable of interpolation -- []
   1314     - match: '%[qws]\['
   1315       scope: punctuation.definition.string.begin.ruby
   1316       push:
   1317         - meta_scope: meta.string.ruby string.quoted.other.literal.lower.ruby
   1318         - match: '\]'
   1319           scope: punctuation.definition.string.end.ruby
   1320           pop: true
   1321         - match: '\\\]|\\\\'
   1322           scope: constant.character.escape.ruby
   1323         - include: nest-brackets
   1324     # literal incapable of interpolation -- {}
   1325     - match: '%[qws]\{'
   1326       scope: punctuation.definition.string.begin.ruby
   1327       push:
   1328         - meta_scope: meta.string.ruby string.quoted.other.literal.lower.ruby
   1329         - match: '\}'
   1330           scope: punctuation.definition.string.end.ruby
   1331           pop: true
   1332         - match: '\\\}|\\\\'
   1333           scope: constant.character.escape.ruby
   1334         - include: nest-curly
   1335     # literal incapable of interpolation -- wildcard
   1336     - match: '%[qws]([^\w])'
   1337       scope: punctuation.definition.string.begin.ruby
   1338       push:
   1339         - meta_scope: meta.string.ruby string.quoted.other.literal.lower.ruby
   1340         - match: \1
   1341           scope: punctuation.definition.string.end.ruby
   1342           pop: true
   1343         # Cant be named because its not necessarily an escape
   1344         - match: \\.
   1345     # symbol literal incapable of interpolation -- ()
   1346     - match: '%i\('
   1347       scope: punctuation.definition.string.begin.ruby
   1348       push:
   1349         - meta_scope: string.quoted.other.literal.lower.ruby
   1350         - match: '\w+'
   1351           scope: constant.other.symbol.ruby
   1352         - match: \)
   1353           scope: punctuation.definition.string.end.ruby
   1354           pop: true
   1355         - match: \\\)|\\\\
   1356           scope: constant.character.escape.ruby
   1357         - include: nest-parens
   1358     # symbol literal incapable of interpolation -- <>
   1359     - match: '%i\<'
   1360       scope: punctuation.definition.string.begin.ruby
   1361       push:
   1362         - meta_scope: string.quoted.other.literal.lower.ruby
   1363         - match: '\w+'
   1364           scope: constant.other.symbol.ruby
   1365         - match: \>
   1366           scope: punctuation.definition.string.end.ruby
   1367           pop: true
   1368         - match: \\\>|\\\\
   1369           scope: constant.character.escape.ruby
   1370         - include: nest-ltgt
   1371     # symbol literal incapable of interpolation -- []
   1372     - match: '%i\['
   1373       scope: punctuation.definition.string.begin.ruby
   1374       push:
   1375         - meta_scope: string.quoted.other.literal.lower.ruby
   1376         - match: '\w+'
   1377           scope: constant.other.symbol.ruby
   1378         - match: '\]'
   1379           scope: punctuation.definition.string.end.ruby
   1380           pop: true
   1381         - match: '\\\]|\\\\'
   1382           scope: constant.character.escape.ruby
   1383         - include: nest-brackets
   1384     # symbol literal incapable of interpolation -- {}
   1385     - match: '%i\{'
   1386       scope: punctuation.definition.string.begin.ruby
   1387       push:
   1388         - meta_scope: string.quoted.other.literal.lower.ruby
   1389         - match: '\w+'
   1390           scope: constant.other.symbol.ruby
   1391         - match: '\}'
   1392           scope: punctuation.definition.string.end.ruby
   1393           pop: true
   1394         - match: '\\\}|\\\\'
   1395           scope: constant.character.escape.ruby
   1396         - include: nest-curly
   1397     # symbol literal incapable of interpolation -- wildcard
   1398     - match: '%i([^\w])'
   1399       scope: punctuation.definition.string.begin.ruby
   1400       push:
   1401         - meta_scope: string.quoted.other.literal.lower.ruby
   1402         - match: '\w+'
   1403           scope: constant.other.symbol.ruby
   1404         - match: \1
   1405           scope: punctuation.definition.string.end.ruby
   1406           pop: true
   1407         # Cant be named because its not necessarily an escape
   1408         - match: \\.
   1409 
   1410   after-keyword:
   1411     - include: try-regex
   1412 
   1413   after-operator:
   1414     - include: try-regex
   1415 
   1416   try-regex:
   1417     # Generally for multiline regexes, one of the %r forms below will be used,
   1418     # so we bail out if we can't find a second / on the current line
   1419     - match: \s*(/)(?=(?!=).*/)
   1420       captures:
   1421         1: punctuation.definition.string.begin.ruby
   1422       push:
   1423         - meta_scope: meta.string.regexp.ruby string.regexp.classic.ruby
   1424         - match: (/)([eimnosux]*)
   1425           captures:
   1426             1: punctuation.definition.string.end.ruby
   1427             2: keyword.other.ruby
   1428           pop: true
   1429         - include: regex-sub
   1430     - match: ''
   1431       pop: true
   1432 
   1433   regexes:
   1434     # Needs higher precedence than regular expressions.
   1435     - match: /=
   1436       scope: keyword.operator.assignment.augmented.ruby
   1437     - match: '(?=^\s*/)'
   1438       push: try-regex
   1439     - match: (?=/\s*[^\w\(\s@"'])
   1440       push: try-regex
   1441     # regular expressions (literal)
   1442     - match: '%r\{'
   1443       scope: punctuation.definition.string.begin.ruby
   1444       push:
   1445         - meta_scope: meta.string.ruby string.regexp.mod-r.ruby
   1446         - match: '\}[eimnosux]*'
   1447           scope: punctuation.definition.string.end.ruby
   1448           pop: true
   1449         - include: regex-sub
   1450         - include: nest-curly-r
   1451     # regular expressions (literal)
   1452     - match: '%r\['
   1453       scope: punctuation.definition.string.begin.ruby
   1454       push:
   1455         - meta_scope: meta.string.ruby string.regexp.mod-r.ruby
   1456         - match: '\][eimnosux]*'
   1457           scope: punctuation.definition.string.end.ruby
   1458           pop: true
   1459         - include: regex-sub
   1460         - include: nest-brackets-r
   1461     # regular expressions (literal)
   1462     - match: '%r\('
   1463       scope: punctuation.definition.string.begin.ruby
   1464       push:
   1465         - meta_scope: meta.string.ruby string.regexp.mod-r.ruby
   1466         - match: '\)[eimnosux]*'
   1467           scope: punctuation.definition.string.end.ruby
   1468           pop: true
   1469         - include: regex-sub
   1470         - include: nest-parens-r
   1471     # regular expressions (literal)
   1472     - match: '%r\<'
   1473       scope: punctuation.definition.string.begin.ruby
   1474       push:
   1475         - meta_scope: meta.string.ruby string.regexp.mod-r.ruby
   1476         - match: '\>[eimnosux]*'
   1477           scope: punctuation.definition.string.end.ruby
   1478           pop: true
   1479         - include: regex-sub
   1480         - include: nest-ltgt-r
   1481     # regular expressions (literal)
   1482     - match: '%r([^\w])'
   1483       scope: punctuation.definition.string.begin.ruby
   1484       push:
   1485         - meta_scope: meta.string.ruby string.regexp.mod-r.ruby
   1486         - match: '\1[eimnosux]*'
   1487           scope: punctuation.definition.string.end.ruby
   1488           pop: true
   1489         - include: regex-sub
   1490 
   1491   regex-sub:
   1492     - include: interpolated-ruby
   1493     - include: escaped-char
   1494     - match: '(\{)\d+(,\d+)?(\})'
   1495       scope: meta.string.ruby string.regexp.arbitrary-repetition.ruby
   1496       captures:
   1497         1: punctuation.definition.arbitrary-repetition.ruby
   1498         3: punctuation.definition.arbitrary-repetition.ruby
   1499     - match: '\[(?:\^?\])?'
   1500       scope: punctuation.definition.character-class.ruby
   1501       push:
   1502         - meta_scope: meta.string.ruby string.regexp.character-class.ruby
   1503         - match: '\]'
   1504           scope: punctuation.definition.character-class.ruby
   1505           pop: true
   1506         - include: escaped-char
   1507     - match: \(
   1508       scope: punctuation.definition.group.ruby
   1509       push:
   1510         - meta_scope: meta.string.ruby string.regexp.group.ruby
   1511         - match: \)
   1512           scope: punctuation.definition.group.ruby
   1513           pop: true
   1514         - include: regex-sub
   1515     # We are restrictive in what we allow to go after the comment character to
   1516     # avoid false positives, since the availability of comments depend on regexp
   1517     # flags.
   1518     - match: '(?:^|\s)(#)\s[[a-zA-Z0-9,. \t?!-][^\x{00}-\x{7F}]]*$'
   1519       scope: comment.line.number-sign.ruby
   1520       captures:
   1521         1: punctuation.definition.comment.ruby
   1522 
   1523   nest-brackets-r:
   1524     - match: '\['
   1525       scope: punctuation.section.scope.ruby
   1526       push:
   1527         - match: '\]'
   1528           scope: punctuation.section.scope.ruby
   1529           pop: true
   1530         - include: regex-sub
   1531         - include: nest-brackets-r
   1532   nest-curly-r:
   1533     - match: '\{'
   1534       scope: punctuation.section.scope.ruby
   1535       push:
   1536         - match: '\}'
   1537           scope: punctuation.section.scope.ruby
   1538           pop: true
   1539         - include: regex-sub
   1540         - include: nest-curly-r
   1541   nest-ltgt-r:
   1542     - match: \<
   1543       scope: punctuation.section.scope.ruby
   1544       push:
   1545         - match: \>
   1546           scope: punctuation.section.scope.ruby
   1547           pop: true
   1548         - include: regex-sub
   1549         - include: nest-ltgt-r
   1550   nest-parens-r:
   1551     - match: \(
   1552       scope: punctuation.section.scope.ruby
   1553       push:
   1554         - match: \)
   1555           scope: punctuation.section.scope.ruby
   1556           pop: true
   1557         - include: regex-sub
   1558         - include: nest-parens-r
   1559 
   1560   nest-brackets:
   1561     - match: '\['
   1562       scope: punctuation.section.scope.ruby
   1563       push:
   1564         - match: '\]'
   1565           scope: punctuation.section.scope.ruby
   1566           pop: true
   1567         - include: nest-brackets
   1568   nest-curly:
   1569     - match: '\{'
   1570       scope: punctuation.section.scope.ruby
   1571       push: [nest-curly-inner, maybe-block-parameters]
   1572   nest-curly-inner:
   1573     - match: '\}'
   1574       scope: punctuation.section.scope.ruby
   1575       pop: true
   1576     - include: nest-curly
   1577   nest-ltgt:
   1578     - match: \<
   1579       scope: punctuation.section.scope.ruby
   1580       push:
   1581         - match: \>
   1582           scope: punctuation.section.scope.ruby
   1583           pop: true
   1584         - include: nest-ltgt
   1585   nest-parens:
   1586     - match: \(
   1587       scope: punctuation.section.scope.ruby
   1588       push:
   1589         - match: \)
   1590           scope: punctuation.section.scope.ruby
   1591           pop: true
   1592         - include: nest-parens
   1593 
   1594   string-placeholder:
   1595     # %[flags][width][.precision]type
   1596     #
   1597     # A format sequence consists of a percent sign, followed by optional
   1598     # flags, width, and precision indicators, then terminated with a field
   1599     # type character.
   1600     #
   1601     # Also this is used for time format in strftime.
   1602     - match: |-
   1603         (?x)%
   1604         ([#0\- +\*]|(\d+\$))*                       # flags
   1605         (-?\d+)?                                    # minimum field width
   1606         (\.(\d+)?)?                                 # precision
   1607         [diouxXDOUeEfFgGaAcCsSpnvtTbByYhHmMzZ%]     # conversion type
   1608       scope: constant.other.placeholder.ruby
   1609 
   1610   escaped-char:
   1611     # SEE: https://ruby-doc.org/core-2.6.3/doc/syntax/literals_rdoc.html
   1612     # meta control sequence
   1613     - match: (?:\\(?:[MC]-|c)){1,2}[[:ascii:]]
   1614       scope: constant.character.escape.ruby
   1615     # extended unicode character
   1616     - match: \\u\{
   1617       push:
   1618         - meta_scope: constant.character.escape.ruby
   1619         - match: \}
   1620           pop: true
   1621         - match: \h{0,6}
   1622         - match: \S
   1623           scope: invalid.illegal.escape.ruby
   1624     # octal, hex, unicode, normal escaped character
   1625     - match: \\(?:[0-7]{1,3}|x\h{1,2}|u\h{4}|.)
   1626       scope: constant.character.escape.ruby
   1627 
   1628   interpolated-ruby:
   1629     - match: '#\{'
   1630       scope: punctuation.section.interpolation.begin.ruby
   1631       push:
   1632         - clear_scopes: 1 # remove `string`/`constant`
   1633         - meta_scope: meta.interpolation.ruby
   1634         - meta_content_scope: source.ruby.embedded.ruby
   1635         - include: interpolated-ruby-expressions
   1636     - match: '(?=#[@$])'
   1637       push:
   1638         - clear_scopes: 1 # remove `string`/`constant`
   1639         - meta_scope: meta.interpolation.ruby
   1640         - include: interpolated-ruby-variables
   1641 
   1642   interpolated-heredoc-ruby:
   1643     - match: '#\{'
   1644       scope: punctuation.section.interpolation.begin.ruby
   1645       push:
   1646         - meta_scope: meta.interpolation.ruby
   1647         - meta_content_scope: source.ruby.embedded.ruby
   1648         - include: interpolated-ruby-expressions
   1649     - match: '(?=#[@$])'
   1650       push:
   1651         - meta_scope: meta.interpolation.ruby
   1652         - include: interpolated-ruby-variables
   1653 
   1654   interpolated-ruby-expressions:
   1655     - match: '\}'
   1656       scope: punctuation.section.interpolation.end.ruby
   1657       pop: true
   1658     - include: nest-curly-expressions
   1659     - include: expressions
   1660 
   1661   interpolated-ruby-variables:
   1662     - match: '(#@)[[:alpha:]_]\w*'
   1663       scope: variable.other.readwrite.instance.ruby
   1664       captures:
   1665         1: punctuation.definition.variable.ruby
   1666       pop: true
   1667     - match: '(#@@)[[:alpha:]_]\w*'
   1668       scope: variable.other.readwrite.class.ruby
   1669       captures:
   1670         1: punctuation.definition.variable.ruby
   1671       pop: true
   1672     - match: '(#\$)[[:alpha:]_]\w*'
   1673       scope: variable.other.readwrite.global.ruby
   1674       captures:
   1675         1: punctuation.definition.variable.ruby
   1676       pop: true
   1677     - match: ''
   1678       pop: true
   1679 
   1680   nest-curly-expressions:
   1681     - match: '\{'
   1682       scope: punctuation.section.scope.ruby
   1683       push: [nest-curly-expressions-inner, maybe-block-parameters]
   1684   nest-curly-expressions-inner:
   1685     - match: '\}'
   1686       scope: punctuation.section.scope.ruby
   1687       pop: true
   1688     - include: nest-curly-expressions
   1689     - include: expressions
   1690 
   1691   nest-all:
   1692     - match: '\('
   1693       scope: punctuation.definition.group.begin.ruby
   1694       push:
   1695         - match: '\)'
   1696           scope: punctuation.definition.group.end.ruby
   1697           pop: true
   1698         - include: nest-all
   1699         - include: expressions
   1700     - match: '\{'
   1701       scope: punctuation.section.scope.ruby
   1702       push: [nest-all-inner, maybe-block-parameters]
   1703     - match: '\['
   1704       scope: punctuation.section.array.ruby
   1705       push:
   1706         - match: '\]'
   1707           scope: punctuation.section.array.ruby
   1708           pop: true
   1709         - include: nest-all
   1710         - include: expressions
   1711   nest-all-inner:
   1712     - match: '\}'
   1713       scope: punctuation.section.scope.ruby
   1714       pop: true
   1715     - include: nest-all
   1716     - include: expressions
   1717 
   1718   nest-brackets-i:
   1719     - match: '\['
   1720       scope: punctuation.section.scope.ruby
   1721       push:
   1722         - match: '\]'
   1723           scope: punctuation.section.scope.ruby
   1724           pop: true
   1725         - include: interpolated-ruby
   1726         - include: escaped-char
   1727         - include: nest-brackets-i
   1728   nest-curly-i:
   1729     - match: '\{'
   1730       scope: punctuation.section.scope.ruby
   1731       push: [nest-curly-i-inner, maybe-block-parameters]
   1732   nest-curly-i-inner:
   1733     - match: '\}'
   1734       scope: punctuation.section.scope.ruby
   1735       pop: true
   1736     - include: interpolated-ruby
   1737     - include: escaped-char
   1738     - include: nest-curly-i
   1739   nest-ltgt-i:
   1740     - match: \<
   1741       scope: punctuation.section.scope.ruby
   1742       push:
   1743         - match: \>
   1744           scope: punctuation.section.scope.ruby
   1745           pop: true
   1746         - include: interpolated-ruby
   1747         - include: escaped-char
   1748         - include: nest-ltgt-i
   1749   nest-parens-i:
   1750     - match: \(
   1751       scope: punctuation.section.scope.ruby
   1752       push:
   1753         - match: \)
   1754           scope: punctuation.section.scope.ruby
   1755           pop: true
   1756         - include: interpolated-ruby
   1757         - include: escaped-char
   1758         - include: nest-parens-i
   1759 
   1760 ###[ HEREDOCS ]################################################################
   1761 
   1762   heredocs:
   1763     # SEE: https://ruby-doc.org/core-2.5.0/doc/syntax/literals_rdoc.html
   1764     - include: heredoc-css
   1765     - include: heredoc-js
   1766     - include: heredoc-html
   1767     - include: heredoc-ruby
   1768     - include: heredoc-shell
   1769     - include: heredoc-sql
   1770     - include: heredoc-plain
   1771 
   1772   heredoc-css:
   1773     - match: (<<[-~])(["`]?)({{heredoc_type_css}})(["`]?)
   1774       captures:
   1775         1: punctuation.definition.heredoc.ruby
   1776         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1777         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1778         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1779       push: [heredoc-css-indented-interpolated, trailing-heredoc-start]
   1780     - match: (<<[-~])(')({{heredoc_type_css}})(')
   1781       captures:
   1782         1: punctuation.definition.heredoc.ruby
   1783         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1784         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1785         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1786       push: [heredoc-css-indented-literal, trailing-heredoc-start]
   1787     - match: (<<)(["`]?)({{heredoc_type_css}})(["`]?)
   1788       captures:
   1789         1: punctuation.definition.heredoc.ruby
   1790         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1791         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1792         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1793       push: [heredoc-css-unindented-interpolated, trailing-heredoc-start]
   1794     - match: (<<)(')({{heredoc_type_css}})(')
   1795       captures:
   1796         1: punctuation.definition.heredoc.ruby
   1797         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1798         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1799         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1800       push: [heredoc-css-unindented-literal, trailing-heredoc-start]
   1801 
   1802   heredoc-css-indented-interpolated:
   1803     - meta_scope: meta.string.heredoc.ruby
   1804     - meta_content_scope: source.css.embedded.ruby
   1805     - include: indented-heredoc-end
   1806     - include: interpolated-heredoc-ruby
   1807     - include: scope:source.css
   1808     - include: escaped-char
   1809 
   1810   heredoc-css-indented-literal:
   1811     - meta_scope: meta.string.heredoc.ruby
   1812     - meta_content_scope: source.css.embedded.ruby
   1813     - include: indented-heredoc-end
   1814     - include: scope:source.css
   1815 
   1816   heredoc-css-unindented-interpolated:
   1817     - meta_scope: meta.string.heredoc.ruby
   1818     - meta_content_scope: source.css.embedded.ruby
   1819     - include: unindented-heredoc-end
   1820     - include: scope:source.css
   1821     - include: escaped-char
   1822 
   1823   heredoc-css-unindented-literal:
   1824     - meta_scope: meta.string.heredoc.ruby
   1825     - meta_content_scope: source.css.embedded.ruby
   1826     - include: unindented-heredoc-end
   1827     - include: scope:source.css
   1828 
   1829   heredoc-js:
   1830     - match: (<<[-~])(["`]?)({{heredoc_type_js}})(["`]?)
   1831       captures:
   1832         1: punctuation.definition.heredoc.ruby
   1833         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1834         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1835         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1836       push: [heredoc-js-indented-interpolated, trailing-heredoc-start]
   1837     - match: (<<[-~])(')({{heredoc_type_js}})(')
   1838       captures:
   1839         1: punctuation.definition.heredoc.ruby
   1840         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1841         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1842         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1843       push: [heredoc-js-indented-literal, trailing-heredoc-start]
   1844     - match: (<<)(["`]?)({{heredoc_type_js}})(["`]?)
   1845       captures:
   1846         1: punctuation.definition.heredoc.ruby
   1847         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1848         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1849         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1850       push: [heredoc-js-unindented-interpolated, trailing-heredoc-start]
   1851     - match: (<<)(')({{heredoc_type_js}})(')
   1852       captures:
   1853         1: punctuation.definition.heredoc.ruby
   1854         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1855         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1856         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1857       push: [heredoc-js-unindented-literal, trailing-heredoc-start]
   1858 
   1859   heredoc-js-indented-interpolated:
   1860     - meta_scope: meta.string.heredoc.ruby
   1861     - meta_content_scope: source.js.embedded.ruby
   1862     - include: indented-heredoc-end
   1863     - include: interpolated-heredoc-ruby
   1864     - include: scope:source.js
   1865     - include: escaped-char
   1866 
   1867   heredoc-js-indented-literal:
   1868     - meta_scope: meta.string.heredoc.ruby
   1869     - meta_content_scope: source.js.embedded.ruby
   1870     - include: indented-heredoc-end
   1871     - include: scope:source.js
   1872 
   1873   heredoc-js-unindented-interpolated:
   1874     - meta_scope: meta.string.heredoc.ruby
   1875     - meta_content_scope: source.js.embedded.ruby
   1876     - include: unindented-heredoc-end
   1877     - include: scope:source.js
   1878     - include: escaped-char
   1879 
   1880   heredoc-js-unindented-literal:
   1881     - meta_scope: meta.string.heredoc.ruby
   1882     - meta_content_scope: source.js.embedded.ruby
   1883     - include: unindented-heredoc-end
   1884     - include: scope:source.js
   1885 
   1886   heredoc-html:
   1887     - match: (<<[-~])(["`]?)({{heredoc_type_html}})(["`]?)
   1888       captures:
   1889         1: punctuation.definition.heredoc.ruby
   1890         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1891         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1892         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1893       push: [heredoc-html-indented-interpolated, trailing-heredoc-start]
   1894     - match: (<<[-~])(')({{heredoc_type_html}})(')
   1895       captures:
   1896         1: punctuation.definition.heredoc.ruby
   1897         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1898         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1899         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1900       push: [heredoc-html-indented-literal, trailing-heredoc-start]
   1901     - match: (<<)(["`]?)({{heredoc_type_html}})(["`]?)
   1902       captures:
   1903         1: punctuation.definition.heredoc.ruby
   1904         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1905         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1906         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1907       push: [heredoc-html-unindented-interpolated, trailing-heredoc-start]
   1908     - match: (<<)(')({{heredoc_type_html}})(')
   1909       captures:
   1910         1: punctuation.definition.heredoc.ruby
   1911         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1912         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1913         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1914       push: [heredoc-html-unindented-literal, trailing-heredoc-start]
   1915 
   1916   heredoc-html-indented-interpolated:
   1917     - meta_scope: meta.string.heredoc.ruby
   1918     - meta_content_scope: text.html.embedded.ruby
   1919     - include: indented-heredoc-end
   1920     - include: interpolated-heredoc-ruby
   1921     - include: scope:text.html.basic
   1922     - include: escaped-char
   1923 
   1924   heredoc-html-indented-literal:
   1925     - meta_scope: meta.string.heredoc.ruby
   1926     - meta_content_scope: text.html.embedded.ruby
   1927     - include: indented-heredoc-end
   1928     - include: scope:text.html.basic
   1929 
   1930   heredoc-html-unindented-interpolated:
   1931     - meta_scope: meta.string.heredoc.ruby
   1932     - meta_content_scope: text.html.embedded.ruby
   1933     - include: unindented-heredoc-end
   1934     - include: scope:text.html.basic
   1935     - include: escaped-char
   1936 
   1937   heredoc-html-unindented-literal:
   1938     - meta_scope: meta.string.heredoc.ruby
   1939     - meta_content_scope: text.html.embedded.ruby
   1940     - include: unindented-heredoc-end
   1941     - include: scope:text.html.basic
   1942 
   1943   heredoc-ruby:
   1944     - match: (<<[-~])(["`]?)({{heredoc_type_ruby}})(["`]?)
   1945       captures:
   1946         1: punctuation.definition.heredoc.ruby
   1947         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1948         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1949         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1950       push: [heredoc-ruby-indented-interpolated, trailing-heredoc-start]
   1951     - match: (<<[-~])(')({{heredoc_type_ruby}})(')
   1952       captures:
   1953         1: punctuation.definition.heredoc.ruby
   1954         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1955         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1956         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1957       push: [heredoc-ruby-indented-literal, trailing-heredoc-start]
   1958     - match: (<<)(["`]?)({{heredoc_type_ruby}})(["`]?)
   1959       captures:
   1960         1: punctuation.definition.heredoc.ruby
   1961         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1962         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1963         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1964       push: [heredoc-ruby-unindented-interpolated, trailing-heredoc-start]
   1965     - match: (<<)(')({{heredoc_type_ruby}})(')
   1966       captures:
   1967         1: punctuation.definition.heredoc.ruby
   1968         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   1969         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   1970         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   1971       push: [heredoc-ruby-unindented-literal, trailing-heredoc-start]
   1972 
   1973   heredoc-ruby-indented-interpolated:
   1974     - meta_scope: meta.string.heredoc.ruby
   1975     - meta_content_scope: source.ruby.embedded.ruby
   1976     - include: indented-heredoc-end
   1977     - include: interpolated-heredoc-ruby
   1978     - include: escaped-char
   1979     - include: expressions
   1980 
   1981   heredoc-ruby-indented-literal:
   1982     - meta_scope: meta.string.heredoc.ruby
   1983     - meta_content_scope: source.ruby.embedded.ruby
   1984     - include: indented-heredoc-end
   1985     - include: expressions
   1986 
   1987   heredoc-ruby-unindented-interpolated:
   1988     - meta_scope: meta.string.heredoc.ruby
   1989     - meta_content_scope: source.ruby.embedded.ruby
   1990     - include: unindented-heredoc-end
   1991     - include: interpolated-heredoc-ruby
   1992     - include: escaped-char
   1993     - include: expressions
   1994 
   1995   heredoc-ruby-unindented-literal:
   1996     - meta_scope: meta.string.heredoc.ruby
   1997     - meta_content_scope: source.ruby.embedded.ruby
   1998     - include: unindented-heredoc-end
   1999     - include: expressions
   2000 
   2001   heredoc-plain:
   2002     - match: (<<[-~])(["`]?)(\w+)(["`]?)
   2003       captures:
   2004         1: punctuation.definition.heredoc.ruby
   2005         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2006         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2007         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2008       push: [heredoc-plain-indented-interpolated, trailing-heredoc-start]
   2009     - match: (<<[-~])(')(\w+)(')
   2010       captures:
   2011         1: punctuation.definition.heredoc.ruby
   2012         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2013         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2014         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2015       push: [heredoc-plain-indented-literal, trailing-heredoc-start]
   2016     - match: (<<)(["`]?)(\w+)(["`]?)
   2017       captures:
   2018         1: punctuation.definition.heredoc.ruby
   2019         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2020         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2021         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2022       push: [heredoc-plain-unindented-interpolated, trailing-heredoc-start]
   2023     - match: (<<)(')(\w+)(')
   2024       captures:
   2025         1: punctuation.definition.heredoc.ruby
   2026         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2027         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2028         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2029       push: [heredoc-plain-unindented-literal, trailing-heredoc-start]
   2030 
   2031   heredoc-plain-indented-interpolated:
   2032     - meta_scope: meta.string.heredoc.ruby
   2033     - meta_content_scope: string.unquoted.heredoc.ruby
   2034     - include: indented-heredoc-end
   2035     - include: interpolated-ruby
   2036     - include: escaped-char
   2037 
   2038   heredoc-plain-indented-literal:
   2039     - meta_scope: meta.string.heredoc.ruby
   2040     - meta_content_scope: string.unquoted.heredoc.ruby
   2041     - include: indented-heredoc-end
   2042 
   2043   heredoc-plain-unindented-interpolated:
   2044     - meta_scope: meta.string.heredoc.ruby
   2045     - meta_content_scope: string.unquoted.heredoc.ruby
   2046     - include: unindented-heredoc-end
   2047     - include: interpolated-ruby
   2048     - include: escaped-char
   2049 
   2050   heredoc-plain-unindented-literal:
   2051     - meta_scope: meta.string.heredoc.ruby
   2052     - meta_content_scope: string.unquoted.heredoc.ruby
   2053     - include: unindented-heredoc-end
   2054 
   2055   heredoc-shell:
   2056     - match: (<<[-~])(["`]?)({{heredoc_type_shell}})(["`]?)
   2057       captures:
   2058         1: punctuation.definition.heredoc.ruby
   2059         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2060         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2061         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2062       push: [heredoc-shell-indented-interpolated, trailing-heredoc-start]
   2063     - match: (<<[-~])(')({{heredoc_type_shell}})(')
   2064       captures:
   2065         1: punctuation.definition.heredoc.ruby
   2066         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2067         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2068         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2069       push: [heredoc-shell-indented-literal, trailing-heredoc-start]
   2070     - match: (<<)(["`]?)({{heredoc_type_shell}})(["`]?)
   2071       captures:
   2072         1: punctuation.definition.heredoc.ruby
   2073         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2074         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2075         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2076       push: [heredoc-shell-unindented-interpolated, trailing-heredoc-start]
   2077     - match: (<<)(')({{heredoc_type_shell}})(')
   2078       captures:
   2079         1: punctuation.definition.heredoc.ruby
   2080         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2081         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2082         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2083       push: [heredoc-shell-unindented-literal, trailing-heredoc-start]
   2084 
   2085   heredoc-shell-indented-interpolated:
   2086     - meta_scope: meta.string.heredoc.ruby
   2087     - meta_content_scope: source.shell.embedded.ruby
   2088     - include: indented-heredoc-end
   2089     - include: interpolated-heredoc-ruby
   2090     - include: scope:source.shell
   2091     - include: escaped-char
   2092 
   2093   heredoc-shell-indented-literal:
   2094     - meta_scope: meta.string.heredoc.ruby
   2095     - meta_content_scope: source.shell.embedded.ruby
   2096     - include: indented-heredoc-end
   2097     - include: scope:source.shell
   2098 
   2099   heredoc-shell-unindented-interpolated:
   2100     - meta_scope: meta.string.heredoc.ruby
   2101     - meta_content_scope: source.shell.embedded.ruby
   2102     - include: unindented-heredoc-end
   2103     - include: scope:source.shell
   2104     - include: escaped-char
   2105 
   2106   heredoc-shell-unindented-literal:
   2107     - meta_scope: meta.string.heredoc.ruby
   2108     - meta_content_scope: source.shell.embedded.ruby
   2109     - include: unindented-heredoc-end
   2110     - include: scope:source.shell
   2111 
   2112   heredoc-sql:
   2113     - match: (<<[-~])(["`]?)({{heredoc_type_sql}})(["`]?)
   2114       captures:
   2115         1: punctuation.definition.heredoc.ruby
   2116         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2117         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2118         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2119       push: [heredoc-sql-indented-interpolated, trailing-heredoc-start]
   2120     - match: (<<[-~])(')({{heredoc_type_sql}})(')
   2121       captures:
   2122         1: punctuation.definition.heredoc.ruby
   2123         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2124         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2125         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2126       push: [heredoc-sql-indented-literal, trailing-heredoc-start]
   2127     - match: (<<)(["`]?)({{heredoc_type_sql}})(["`]?)
   2128       captures:
   2129         1: punctuation.definition.heredoc.ruby
   2130         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2131         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2132         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2133       push: [heredoc-sql-unindented-interpolated, trailing-heredoc-start]
   2134     - match: (<<)(')({{heredoc_type_sql}})(')
   2135       captures:
   2136         1: punctuation.definition.heredoc.ruby
   2137         2: meta.tag.heredoc.ruby punctuation.definition.tag.begin.ruby
   2138         3: meta.tag.heredoc.ruby entity.name.tag.ruby
   2139         4: meta.tag.heredoc.ruby punctuation.definition.tag.end.ruby
   2140       push: [heredoc-sql-unindented-literal, trailing-heredoc-start]
   2141 
   2142   heredoc-sql-indented-interpolated:
   2143     - meta_scope: meta.string.heredoc.ruby
   2144     - meta_content_scope: source.sql.embedded.ruby
   2145     - include: indented-heredoc-end
   2146     - include: interpolated-heredoc-ruby
   2147     - include: scope:source.sql
   2148     - include: escaped-char
   2149 
   2150   heredoc-sql-indented-literal:
   2151     - meta_scope: meta.string.heredoc.ruby
   2152     - meta_content_scope: source.sql.embedded.ruby
   2153     - include: indented-heredoc-end
   2154     - include: scope:source.sql
   2155 
   2156   heredoc-sql-unindented-interpolated:
   2157     - meta_scope: meta.string.heredoc.ruby
   2158     - meta_content_scope: source.sql.embedded.ruby
   2159     - include: unindented-heredoc-end
   2160     - include: scope:source.sql
   2161     - include: escaped-char
   2162 
   2163   heredoc-sql-unindented-literal:
   2164     - meta_scope: meta.string.heredoc.ruby
   2165     - meta_content_scope: source.sql.embedded.ruby
   2166     - include: unindented-heredoc-end
   2167     - include: scope:source.sql
   2168 
   2169   indented-heredoc-end:
   2170     - match: ^\s*(\3)$ # HEREDOC delimiter
   2171       scope: meta.tag.heredoc.ruby
   2172       captures:
   2173         1: entity.name.tag.ruby
   2174       pop: true
   2175 
   2176   unindented-heredoc-end:
   2177     - match: ^\3$ # HEREDOC delimiter
   2178       scope: meta.tag.heredoc.ruby entity.name.tag.ruby
   2179       pop: true
   2180 
   2181   trailing-heredoc-start:
   2182     # This prevents clear_scopes from applying to the push token
   2183     - match: ''
   2184       set: trailing-heredoc
   2185 
   2186   trailing-heredoc:
   2187     # The rest of the line right after the heredoc tag needs to be handled
   2188     # as ordinary ruby source. The embedded syntax starts at the next line.
   2189     - clear_scopes: 2
   2190     - match: ^
   2191       pop: true
   2192     - include: expressions
   2193 
   2194 ###[ DATA SECTION ]############################################################
   2195 
   2196   data-section:
   2197     - match: ^__END__\n
   2198       scope: meta.string.ruby string.unquoted.program-block.ruby
   2199       push:
   2200         - meta_content_scope: text.plain
   2201         - match: (?=<?xml|<(?i:html\b)|!DOCTYPE (?i:html\b))
   2202           push:
   2203             - meta_scope: text.html.embedded.ruby
   2204             - include: scope:text.html.basic