├── .coffeelintignore ├── .github ├── no-response.yml └── workflows │ └── ci.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── appveyor.yml ├── coffeelint.json ├── grammars ├── gemfile.cson ├── html (ruby - erb).cson ├── ruby.cson └── tree-sitter-ruby.cson ├── lib └── main.js ├── package.json ├── settings └── language-ruby.cson ├── snippets └── language-ruby.cson └── spec ├── erb-spec.coffee ├── gemfile-spec.coffee ├── ruby-spec.coffee └── tree-sitter-spec.js /.coffeelintignore: -------------------------------------------------------------------------------- 1 | spec/fixtures 2 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an issue is closed for lack of response 4 | daysUntilClose: 28 5 | 6 | # Label requiring a response 7 | responseRequiredLabel: more-information-needed 8 | 9 | # Comment to post when closing an issue for lack of response. Set to `false` to disable. 10 | closeComment: > 11 | This issue has been automatically closed because there has been no response 12 | to our request for more information from the original author. With only the 13 | information that is currently in the issue, we don't have enough information 14 | to take action. Please reach out if you have or find the answers we need so 15 | that we can investigate further. 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | - pull_request 4 | - push 5 | 6 | jobs: 7 | Test: 8 | if: "!contains(github.event.head_commit.message, '[skip ci]')" 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | - macos-latest 16 | - windows-latest 17 | atom_channel: 18 | - stable 19 | - nightly 20 | steps: 21 | - uses: actions/checkout@v2 22 | - name: Cache 23 | uses: actions/cache@v2 24 | with: 25 | path: | 26 | 'node_modules' 27 | 'C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/v140' 28 | key: ${{ runner.os }}-${{ matrix.atom_channel }}-${{ hashFiles('package.json') }} 29 | 30 | - uses: UziTech/action-setup-atom@v1 31 | with: 32 | channel: ${{ matrix.atom_channel }} 33 | 34 | - name: Install Visual Studio 2015 on Windows 35 | if: ${{ contains(matrix.os, 'windows') }} 36 | run: | 37 | choco install visualcpp-build-tools --version=14.0.25420.1 --ignore-dependencies -y --params "'/IncludeRequired'" 38 | echo ::set-env name=VCTargetsPath::'C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\v140' 39 | 40 | - name: Install dependencies 41 | run: apm install 42 | 43 | - name: Run tests 44 | run: apm test 45 | 46 | Skip: 47 | if: contains(github.event.head_commit.message, '[skip ci]') 48 | runs-on: ubuntu-latest 49 | steps: 50 | - name: Skip CI 🚫 51 | run: echo skip ci 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See the [Atom contributing guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md) 2 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Prerequisites 10 | 11 | * [ ] Put an X between the brackets on this line if you have done all of the following: 12 | * Reproduced the problem in Safe Mode: http://flight-manual.atom.io/hacking-atom/sections/debugging/#using-safe-mode 13 | * Followed all applicable steps in the debugging guide: http://flight-manual.atom.io/hacking-atom/sections/debugging/ 14 | * Checked the FAQs on the message board for common solutions: https://discuss.atom.io/c/faq 15 | * Checked that your issue isn't already filed: https://github.com/issues?utf8=✓&q=is%3Aissue+user%3Aatom 16 | * Checked that there is not already an Atom package that provides the described functionality: https://atom.io/packages 17 | 18 | ### Description 19 | 20 | [Description of the issue] 21 | 22 | ### Steps to Reproduce 23 | 24 | 1. [First Step] 25 | 2. [Second Step] 26 | 3. [and so on...] 27 | 28 | **Expected behavior:** [What you expect to happen] 29 | 30 | **Actual behavior:** [What actually happens] 31 | 32 | **Reproduces how often:** [What percentage of the time does it reproduce?] 33 | 34 | ### Versions 35 | 36 | You can get this information from copy and pasting the output of `atom --version` and `apm --version` from the command line. Also, please include the OS and what version of the OS you're running. 37 | 38 | ### Additional Information 39 | 40 | Any additional information, configuration or data that might be necessary to reproduce the issue. 41 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 GitHub Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------- 23 | 24 | This package was derived from a TextMate bundle located at 25 | https://github.com/textmate/ruby.tmbundle and distributed under the following 26 | license, located in `README.mdown`: 27 | 28 | Permission to copy, use, modify, sell and distribute this 29 | software is granted. This software is provided "as is" without 30 | express or implied warranty, and with no claim as to its 31 | suitability for any purpose. 32 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Requirements 2 | 3 | * Filling out the template is required. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion. 4 | * All new code requires tests to ensure against regressions 5 | 6 | ### Description of the Change 7 | 8 | 13 | 14 | ### Alternate Designs 15 | 16 | 17 | 18 | ### Benefits 19 | 20 | 21 | 22 | ### Possible Drawbacks 23 | 24 | 25 | 26 | ### Applicable Issues 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##### Atom and all repositories under Atom will be archived on December 15, 2022. Learn more in our [official announcement](https://github.blog/2022-06-08-sunsetting-atom/) 2 | # Ruby language support in Atom 3 | ![ci](https://github.com/atom/language-ruby/workflows/ci/badge.svg) 4 | [![Dependency Status](https://david-dm.org/atom/language-ruby.svg)](https://david-dm.org/atom/language-ruby) 5 | 6 | Adds syntax highlighting and snippets to Ruby files in Atom. 7 | 8 | Originally [converted](http://flight-manual.atom.io/hacking-atom/sections/converting-from-textmate) from the [Ruby TextMate bundle](https://github.com/textmate/ruby.tmbundle). 9 | 10 | Contributions are greatly appreciated. Please fork this repository and open a pull request to add snippets, make grammar tweaks, etc. 11 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # empty appveyor 2 | build: off 3 | 4 | branches: 5 | only: 6 | - non-existing 7 | -------------------------------------------------------------------------------- /coffeelint.json: -------------------------------------------------------------------------------- 1 | { 2 | "max_line_length": { 3 | "level": "ignore" 4 | }, 5 | "no_empty_param_list": { 6 | "level": "error" 7 | }, 8 | "arrow_spacing": { 9 | "level": "error" 10 | }, 11 | "no_interpolation_in_single_quotes": { 12 | "level": "error" 13 | }, 14 | "no_debugger": { 15 | "level": "error" 16 | }, 17 | "prefer_english_operator": { 18 | "level": "error" 19 | }, 20 | "colon_assignment_spacing": { 21 | "spacing": { 22 | "left": 0, 23 | "right": 1 24 | }, 25 | "level": "error" 26 | }, 27 | "braces_spacing": { 28 | "spaces": 0, 29 | "level": "error" 30 | }, 31 | "spacing_after_comma": { 32 | "level": "error" 33 | }, 34 | "no_stand_alone_at": { 35 | "level": "error" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /grammars/gemfile.cson: -------------------------------------------------------------------------------- 1 | 'name': 'Gemfile' 2 | 'scopeName': 'source.ruby.gemfile' 3 | 'fileTypes': [ 4 | 'Gemfile' 5 | ] 6 | 'patterns': [ 7 | { 8 | 'include': 'source.ruby' 9 | } 10 | { 11 | 'begin': '\\b(?))' 12 | 'beginCaptures': 13 | '0': 14 | 'name': 'punctuation.whitespace.comment.leading.erb' 15 | 'end': '(?!\\G)(\\s*$\\n)?' 16 | 'endCaptures': 17 | '0': 18 | 'name': 'punctuation.whitespace.comment.trailing.erb' 19 | 'patterns': [ 20 | { 21 | 'include': '#comment' 22 | } 23 | ] 24 | } 25 | { 26 | 'begin': '(^\\s*)(?=<%(?![^%]*%>))' 27 | 'beginCaptures': 28 | '0': 29 | 'name': 'punctuation.whitespace.embedded.leading.erb' 30 | 'end': '(?!\\G)(\\s*$\\n)?' 31 | 'endCaptures': 32 | '0': 33 | 'name': 'punctuation.whitespace.embedded.trailing.erb' 34 | 'patterns': [ 35 | { 36 | 'include': '#tags' 37 | } 38 | ] 39 | } 40 | { 41 | 'include': '#comment' 42 | } 43 | { 44 | 'include': '#tags' 45 | } 46 | ] 47 | 'patterns': [ 48 | { 49 | 'include': 'text.html.basic' 50 | } 51 | ] 52 | 'repository': 53 | 'comment': 54 | 'patterns': [ 55 | { 56 | 'begin': '<%+#' 57 | 'beginCaptures': 58 | '0': 59 | 'name': 'punctuation.definition.comment.begin.erb' 60 | 'end': '%>' 61 | 'endCaptures': 62 | '0': 63 | 'name': 'punctuation.definition.comment.end.erb' 64 | 'name': 'comment.block.erb' 65 | } 66 | ] 67 | 'tags': 68 | 'patterns': [ 69 | { 70 | 'begin': '<%+(?!>)[-=]?(?![^%]*%>)' 71 | 'beginCaptures': 72 | '0': 73 | 'name': 'punctuation.section.embedded.begin.erb' 74 | 'contentName': 'source.ruby.embedded.erb' 75 | 'end': '-?%>' 76 | 'endCaptures': 77 | '0': 78 | 'name': 'punctuation.section.embedded.end.erb' 79 | '1': 80 | 'name': 'source.ruby' 81 | 'name': 'meta.embedded.block.erb' 82 | 'patterns': [ 83 | { 84 | 'captures': 85 | '1': 86 | 'name': 'punctuation.definition.comment.erb' 87 | 'match': '(#).*?(?=-?%>)' 88 | 'name': 'comment.line.number-sign.erb' 89 | } 90 | { 91 | 'include': 'source.ruby' 92 | } 93 | ] 94 | } 95 | { 96 | 'begin': '<%+(?!>)[-=]?' 97 | 'beginCaptures': 98 | '0': 99 | 'name': 'punctuation.section.embedded.begin.erb' 100 | 'contentName': 'source.ruby.embedded.erb' 101 | 'end': '-?%>' 102 | 'endCaptures': 103 | '0': 104 | 'name': 'punctuation.section.embedded.end.erb' 105 | '1': 106 | 'name': 'source.ruby' 107 | 'name': 'meta.embedded.line.erb' 108 | 'patterns': [ 109 | { 110 | 'captures': 111 | '1': 112 | 'name': 'punctuation.definition.comment.erb' 113 | 'match': '(#).*?(?=-?%>)' 114 | 'name': 'comment.line.number-sign.erb' 115 | } 116 | { 117 | 'include': 'source.ruby' 118 | } 119 | ] 120 | } 121 | ] 122 | -------------------------------------------------------------------------------- /grammars/ruby.cson: -------------------------------------------------------------------------------- 1 | 'name': 'Ruby' 2 | 'scopeName': 'source.ruby' 3 | 'fileTypes': [ 4 | 'Appfile' 5 | 'Appraisals' 6 | 'arb' 7 | 'Berksfile' 8 | 'Brewfile' 9 | 'cap' 10 | 'Capfile' 11 | 'capfile' 12 | 'cgi' 13 | 'cr' 14 | 'Dangerfile' 15 | 'Deliverfile' 16 | 'Fastfile' 17 | 'fcgi' 18 | 'gemspec' 19 | 'Guardfile' 20 | 'irbrc' 21 | 'opal' 22 | 'Podfile' 23 | 'podspec' 24 | 'prawn' 25 | 'pryrc' 26 | 'Puppetfile' 27 | 'rabl' 28 | 'rake' 29 | 'Rakefile' 30 | 'Rantfile' 31 | 'rb' 32 | 'rbx' 33 | 'rjs' 34 | 'ru' 35 | 'ruby' 36 | 'Schemafile' 37 | 'Snapfile' 38 | 'thor' 39 | 'Thorfile' 40 | 'Vagrantfile' 41 | ] 42 | 'firstLineMatch': '''(?x) 43 | # Hashbang 44 | ^\\#!.*(?:\\s|\\/) 45 | (?:ruby|macruby|rake|jruby|rbx|ruby_executable_hooks) 46 | (?:$|\\s) 47 | | 48 | # Modeline 49 | (?i: 50 | # Emacs 51 | -\\*-(?:\\s*(?=[^:;\\s]+\\s*-\\*-)|(?:.*?[;\\s]|(?<=-\\*-))mode\\s*:\\s*) 52 | ruby 53 | (?=[\\s;]|(?]?\\d+|m)?|\\sex)(?=:(?=\\s*set?\\s[^\\n:]+:)|:(?!\\s*set?\\s))(?:(?:\\s|\\s*:\\s*)\\w*(?:\\s*=(?:[^\\n\\\\\\s]|\\\\.)*)?)*[\\s:](?:filetype|ft|syntax)\\s*= 57 | ruby 58 | (?=\\s|:|$) 59 | ) 60 | ''' 61 | 'patterns': [ 62 | { 63 | 'begin': '\\bclass\\b' 64 | 'beginCaptures': 65 | '0': 66 | 'name': 'keyword.control.class.ruby' 67 | 'end': '\\s*$|(?![\\s\\w.:<])' 68 | 'name': 'meta.class.ruby' 69 | 'patterns': [ 70 | { 71 | 'match': '[A-Z]\\w*' 72 | 'name': 'entity.name.type.class.ruby' 73 | } 74 | { 75 | 'include': '#separators' 76 | } 77 | { 78 | 'begin': '(<<)\\s*' 79 | 'beginCaptures': 80 | '1': 81 | 'name': 'punctuation.definition.variable.ruby' 82 | 'contentName': 'variable.other.object.ruby' 83 | 'end': '(?=$)|(?![\\s\\w.:])' 84 | 'patterns': [ 85 | { 86 | 'match': '[A-Z]\\w*' 87 | 'name': 'entity.name.type.class.ruby' 88 | } 89 | { 90 | 'include': '#separators' 91 | } 92 | ] 93 | } 94 | { 95 | 'begin': '(<)\\s*' 96 | 'beginCaptures': 97 | '1': 98 | 'name': 'punctuation.separator.inheritance.ruby' 99 | 'contentName': 'entity.other.inherited-class.ruby' 100 | 'end': '(?=$)|(?![\\s\\w.:])' 101 | 'patterns': [ 102 | { 103 | 'match': '[A-Z]\\w*' 104 | 'name': 'entity.name.type.class.ruby' 105 | } 106 | { 107 | 'include': '#separators' 108 | } 109 | ] 110 | } 111 | ] 112 | } 113 | { 114 | 'begin': '\\bmodule\\b' 115 | 'beginCaptures': 116 | '0': 117 | 'name': 'keyword.control.module.ruby' 118 | 'end': '\\s*$|(?![\\s\\w.:])' 119 | 'name': 'meta.module.ruby' 120 | 'patterns': [ 121 | { 122 | 'match': '[A-Z]\\w*(?=::)' 123 | 'name': 'entity.other.inherited-class.module.ruby' 124 | } 125 | { 126 | 'match': '[A-Z]\\w*' 127 | 'name': 'entity.name.type.module.ruby' 128 | } 129 | { 130 | 'include': '#separators' 131 | } 132 | ] 133 | } 134 | { 135 | 'comment': 'else if is a common mistake carried over from other languages. it works if you put in a second end, but it’s never what you want.' 136 | 'match': '(?[a-zA-Z_]\\w*(?>[?!])?)(:)(?!:)' 145 | 'name': 'constant.other.symbol.hashkey.ruby' 146 | } 147 | { 148 | 'captures': 149 | '1': 150 | 'name': 'punctuation.definition.constant.ruby' 151 | 'comment': 'symbols as hash key (1.8 syntax)' 152 | 'match': '(?[a-zA-Z_]\\w*(?>[?!])?)(?=\\s*=>)' 153 | 'name': 'constant.other.symbol.hashkey.ruby' 154 | } 155 | { 156 | 'comment': 'everything being a reserved word, not a value and needing a \'end\' is a..' 157 | 'match': '(?|_|\\*|\\$|\\?|:|"|-[0adFiIlpv])' 234 | 'name': 'variable.other.readwrite.global.pre-defined.ruby' 235 | } 236 | { 237 | 'begin': '\\b(ENV)\\[' 238 | 'beginCaptures': 239 | '1': 240 | 'name': 'variable.other.constant.ruby' 241 | 'end': ']' 242 | 'name': 'meta.environment-variable.ruby' 243 | 'patterns': [ 244 | { 245 | 'include': '$self' 246 | } 247 | ] 248 | } 249 | { 250 | 'match': '\\b[A-Z]\\w*(?=((\\.|::)[A-Za-z]|\\[))' 251 | 'name': 'support.class.ruby' 252 | } 253 | { 254 | 'match': '\\b((abort|at_exit|autoload|binding|callcc|caller|caller_locations|chomp|chop|eval|exec|exit|fork|format|gets|global_variables|gsub|lambda|load|local_variables|open|p|print|printf|proc|putc|puts|rand|readline|readlines|select|set_trace_func|sleep|spawn|sprintf|srand|sub|syscall|system|test|trace_var|trap|untrace_var|warn)\\b(?![?!])|autoload\\?|exit!)' 255 | 'name': 'support.function.kernel.ruby' 256 | } 257 | { 258 | 'match': '\\b[_A-Z]\\w*\\b' 259 | 'name': 'variable.other.constant.ruby' 260 | } 261 | { 262 | 'begin': '''(?x) 263 | (?=def\\b) # optimization to help Oniguruma fail fast 264 | (?<=^|\\s)(def)\\s+ 265 | ( 266 | (?:(self)(\\.|::))? 267 | (?>[a-zA-Z_]\\w*(?>(\\.|::)))* # method prefix 268 | (?> # method name 269 | [a-zA-Z_]\\w*(?>[?!]|=(?!>))? 270 | | 271 | ===?|!=|>[>=]?|<=>|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[]=? 272 | ) 273 | ) 274 | \\s*(\\() 275 | ''' 276 | 'beginCaptures': 277 | '1': 278 | 'name': 'keyword.control.def.ruby' 279 | '2': 280 | 'name': 'entity.name.function.ruby' 281 | '3': 282 | 'name': 'variable.language.self.ruby' 283 | '4': 284 | 'name': 'punctuation.separator.method.ruby' 285 | '5': 286 | 'comment': 'Unfortunately, the repeated pattern (\\.|::)* only captures the last occurring separator' 287 | 'name': 'punctuation.separator.method.ruby' 288 | '6': 289 | 'name': 'punctuation.definition.parameters.ruby' 290 | 'comment': 'The method pattern comes from the symbol pattern. See there for an explanation.' 291 | 'end': '\\)' 292 | 'endCaptures': 293 | '0': 294 | 'name': 'punctuation.definition.parameters.ruby' 295 | 'name': 'meta.function.method.with-arguments.ruby' 296 | 'patterns': [ 297 | { 298 | 'begin': '(?![\\s,)])' 299 | 'end': '(?=,|\\)\\s*$)' 300 | 'patterns': [ 301 | { 302 | 'captures': 303 | '1': 304 | 'name': 'storage.type.variable.ruby' 305 | '2': 306 | 'name': 'constant.other.symbol.hashkey.parameter.function.ruby' 307 | '3': 308 | 'name': 'punctuation.definition.constant.hashkey.ruby' 309 | '4': 310 | 'name': 'variable.parameter.function.ruby' 311 | 'match': '\\G([&*]?)(?:([_a-zA-Z]\\w*(:))|([_a-zA-Z]\\w*))' 312 | } 313 | { 314 | 'include': '$self' 315 | } 316 | ] 317 | } 318 | { 319 | 'match': ',' 320 | 'name': 'punctuation.separator.delimiter.ruby' 321 | } 322 | ] 323 | } 324 | { 325 | 'begin': '''(?x) 326 | (?=def\\b) # optimization to help Oniguruma fail fast 327 | (?<=^|\\s)(def)\\s+ 328 | ( 329 | (?:(self)(\\.|::))? 330 | (?>[a-zA-Z_]\\w*(?>(\\.|::)))* # method prefix 331 | (?> # method name 332 | [a-zA-Z_]\\w*(?>[?!]|=(?!>))? 333 | | 334 | ===?|!=|>[>=]?|<=>|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[]=? 335 | ) 336 | ) 337 | [ \\t] 338 | (?=[ \\t]*[^\\s#;]) # make sure the following is not comment 339 | ''' 340 | 'beginCaptures': 341 | '1': 342 | 'name': 'keyword.control.def.ruby' 343 | '2': 344 | 'name': 'entity.name.function.ruby' 345 | '3': 346 | 'name': 'variable.language.self.ruby' 347 | '4': 348 | 'name': 'punctuation.separator.method.ruby' 349 | '5': 350 | 'comment': 'Unfortunately, the repeated pattern (\\.|::)* only captures the last occurring separator' 351 | 'name': 'punctuation.separator.method.ruby' 352 | 'comment': 'same as the previous rule, but without parentheses around the arguments' 353 | 'end': '$' 354 | 'name': 'meta.function.method.with-arguments.ruby' 355 | 'patterns': [ 356 | { 357 | 'begin': '(?![\\s,])' 358 | 'end': '(?=,|$)' 359 | 'patterns': [ 360 | { 361 | 'captures': 362 | '1': 363 | 'name': 'storage.type.variable.ruby' 364 | '2': 365 | 'name': 'constant.other.symbol.hashkey.parameter.function.ruby' 366 | '3': 367 | 'name': 'punctuation.definition.constant.hashkey.ruby' 368 | '4': 369 | 'name': 'variable.parameter.function.ruby' 370 | 'match': '\\G([&*]?)(?:([_a-zA-Z]\\w*(:))|([_a-zA-Z]\\w*))' 371 | } 372 | { 373 | 'include': '$self' 374 | } 375 | ] 376 | } 377 | { 378 | 'match': ',' 379 | 'name': 'punctuation.separator.delimiter.ruby' 380 | } 381 | ] 382 | } 383 | { 384 | 'captures': 385 | '1': 386 | 'name': 'keyword.control.def.ruby' 387 | '3': 388 | 'name': 'entity.name.function.ruby' 389 | '4': 390 | 'name': 'variable.language.self.ruby' 391 | '5': 392 | 'name': 'punctuation.separator.method.ruby' 393 | '6': 394 | 'comment': 'Unfortunately, the repeated pattern (\\.|::)* only captures the last occurring separator' 395 | 'name': 'punctuation.separator.method.ruby' 396 | 'comment': ' the optional name is just to catch the def also without a method-name' 397 | 'match': '''(?x) 398 | (?=def\\b) # optimization to help Oniguruma fail fast 399 | (?<=^|\\s)(def)\\b 400 | ( 401 | \\s+ 402 | ( 403 | (?:(self)(\\.|::))? 404 | (?>[a-zA-Z_]\\w*(?>(\\.|::)))* # method prefix 405 | (?> # method name 406 | [a-zA-Z_]\\w*(?>[?!]|=(?!>))? 407 | | 408 | ===?|!=|>[>=]?|<=>|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[]=? 409 | ) 410 | ) 411 | )? 412 | ''' 413 | 'name': 'meta.function.method.without-arguments.ruby' 414 | } 415 | { 416 | 'match': '''(?x) 417 | \\b 418 | ( 419 | [\\d](?>_?\\d)* # 100_000 420 | (\\.(?![^[:space:][:digit:]])(?>_?\\d)*)? # fractional part 421 | ([eE][-+]?\\d(?>_?\\d)*)? # 1.23e-4 422 | | 423 | 0 424 | (?: 425 | [xX]\\h(?>_?\\h)*| 426 | [oO]?[0-7](?>_?[0-7])*| 427 | [bB][01](?>_?[01])*| 428 | [dD]\\d(?>_?\\d)* 429 | ) # A base indicator can only be used with an integer 430 | )\\b 431 | ''' 432 | 'name': 'constant.numeric.ruby' 433 | } 434 | { 435 | 'begin': ':\'' 436 | 'beginCaptures': 437 | '0': 438 | 'name': 'punctuation.definition.symbol.begin.ruby' 439 | 'comment': "symbol literal with '' delimiter" 440 | 'end': '\'' 441 | 'endCaptures': 442 | '0': 443 | 'name': 'punctuation.definition.symbol.end.ruby' 444 | 'name': 'constant.other.symbol.ruby' 445 | 'patterns': [ 446 | { 447 | 'match': '\\\\[\'\\\\]' 448 | 'name': 'constant.character.escape.ruby' 449 | } 450 | ] 451 | } 452 | { 453 | 'begin': ':"' 454 | 'beginCaptures': 455 | '0': 456 | 'name': 'punctuation.section.symbol.begin.ruby' 457 | 'comment': 'symbol literal with "" delimiter' 458 | 'end': '"' 459 | 'endCaptures': 460 | '0': 461 | 'name': 'punctuation.section.symbol.end.ruby' 462 | 'name': 'constant.other.symbol.interpolated.ruby' 463 | 'patterns': [ 464 | { 465 | 'include': '#interpolated_ruby' 466 | } 467 | { 468 | 'include': '#escaped_char' 469 | } 470 | ] 471 | } 472 | { 473 | 'comment': 'Needs higher precedence than regular expressions.' 474 | 'match': '(?|=>|==|=~|!~|!=|;|$| 543 | if|else|elsif|then|do|end|unless|while|until|or|and 544 | ) 545 | | 546 | $ 547 | ) 548 | ''' 549 | 'captures': 550 | '1': 551 | 'name': 'string.regexp.interpolated.ruby' 552 | '2': 553 | 'name': 'punctuation.section.regexp.ruby' 554 | 'comment': 'regular expression literal with interpolation' 555 | 'contentName': 'string.regexp.interpolated.ruby' 556 | 'end': '((/[eimnosux]*))' 557 | 'patterns': [ 558 | { 559 | 'include': '#regex_sub' 560 | } 561 | ] 562 | } 563 | { 564 | 'begin': '%r{' 565 | 'beginCaptures': 566 | '0': 567 | 'name': 'punctuation.section.regexp.begin.ruby' 568 | 'end': '}[eimnosux]*' 569 | 'endCaptures': 570 | '0': 571 | 'name': 'punctuation.section.regexp.end.ruby' 572 | 'name': 'string.regexp.interpolated.ruby' 573 | 'patterns': [ 574 | { 575 | 'include': '#regex_sub' 576 | } 577 | { 578 | 'include': '#nest_curly_r' 579 | } 580 | ] 581 | } 582 | { 583 | 'begin': '%r\\[' 584 | 'beginCaptures': 585 | '0': 586 | 'name': 'punctuation.section.regexp.begin.ruby' 587 | 'end': '][eimnosux]*' 588 | 'endCaptures': 589 | '0': 590 | 'name': 'punctuation.section.regexp.end.ruby' 591 | 'name': 'string.regexp.interpolated.ruby' 592 | 'patterns': [ 593 | { 594 | 'include': '#regex_sub' 595 | } 596 | { 597 | 'include': '#nest_brackets_r' 598 | } 599 | ] 600 | } 601 | { 602 | 'begin': '%r\\(' 603 | 'beginCaptures': 604 | '0': 605 | 'name': 'punctuation.section.regexp.begin.ruby' 606 | 'end': '\\)[eimnosux]*' 607 | 'endCaptures': 608 | '0': 609 | 'name': 'punctuation.section.regexp.end.ruby' 610 | 'name': 'string.regexp.interpolated.ruby' 611 | 'patterns': [ 612 | { 613 | 'include': '#regex_sub' 614 | } 615 | { 616 | 'include': '#nest_parens_r' 617 | } 618 | ] 619 | } 620 | { 621 | 'begin': '%r<' 622 | 'beginCaptures': 623 | '0': 624 | 'name': 'punctuation.section.regexp.begin.ruby' 625 | 'end': '>[eimnosux]*' 626 | 'endCaptures': 627 | '0': 628 | 'name': 'punctuation.section.regexp.end.ruby' 629 | 'name': 'string.regexp.interpolated.ruby' 630 | 'patterns': [ 631 | { 632 | 'include': '#regex_sub' 633 | } 634 | { 635 | 'include': '#nest_ltgt_r' 636 | } 637 | ] 638 | } 639 | { 640 | 'begin': '%r([^\\w])' 641 | 'beginCaptures': 642 | '0': 643 | 'name': 'punctuation.section.regexp.begin.ruby' 644 | 'end': '\\1[eimnosux]*' 645 | 'endCaptures': 646 | '0': 647 | 'name': 'punctuation.section.regexp.end.ruby' 648 | 'name': 'string.regexp.interpolated.ruby' 649 | 'patterns': [ 650 | { 651 | 'include': '#regex_sub' 652 | } 653 | ] 654 | } 655 | { 656 | 'begin': '%I\\[' 657 | 'beginCaptures': 658 | '0': 659 | 'name': 'punctuation.section.array.begin.ruby' 660 | 'end': ']' 661 | 'endCaptures': 662 | '0': 663 | 'name': 'punctuation.section.array.end.ruby' 664 | 'name': 'constant.other.symbol.interpolated.ruby' 665 | 'patterns': [ 666 | { 667 | 'include': '#interpolated_ruby' 668 | } 669 | { 670 | 'include': '#escaped_char' 671 | } 672 | { 673 | 'include': '#nest_brackets_i' 674 | } 675 | ] 676 | } 677 | { 678 | 'begin': '%I\\(' 679 | 'beginCaptures': 680 | '0': 681 | 'name': 'punctuation.section.array.begin.ruby' 682 | 'end': '\\)' 683 | 'endCaptures': 684 | '0': 685 | 'name': 'punctuation.section.array.end.ruby' 686 | 'name': 'constant.other.symbol.interpolated.ruby' 687 | 'patterns': [ 688 | { 689 | 'include': '#interpolated_ruby' 690 | } 691 | { 692 | 'include': '#escaped_char' 693 | } 694 | { 695 | 'include': '#nest_parens_i' 696 | } 697 | ] 698 | } 699 | { 700 | 'begin': '%I<' 701 | 'beginCaptures': 702 | '0': 703 | 'name': 'punctuation.section.array.begin.ruby' 704 | 'end': '>' 705 | 'endCaptures': 706 | '0': 707 | 'name': 'punctuation.section.array.end.ruby' 708 | 'name': 'constant.other.symbol.interpolated.ruby' 709 | 'patterns': [ 710 | { 711 | 'include': '#interpolated_ruby' 712 | } 713 | { 714 | 'include': '#escaped_char' 715 | } 716 | { 717 | 'include': '#nest_ltgt_i' 718 | } 719 | ] 720 | } 721 | { 722 | 'begin': '%I{' 723 | 'beginCaptures': 724 | '0': 725 | 'name': 'punctuation.section.array.begin.ruby' 726 | 'end': '}' 727 | 'endCaptures': 728 | '0': 729 | 'name': 'punctuation.section.array.end.ruby' 730 | 'name': 'constant.other.symbol.interpolated.ruby' 731 | 'patterns': [ 732 | { 733 | 'include': '#interpolated_ruby' 734 | } 735 | { 736 | 'include': '#escaped_char' 737 | } 738 | { 739 | 'include': '#nest_curly_i' 740 | } 741 | ] 742 | } 743 | { 744 | 'begin': '%I([^\\w])' 745 | 'beginCaptures': 746 | '0': 747 | 'name': 'punctuation.section.array.begin.ruby' 748 | 'end': '\\1' 749 | 'endCaptures': 750 | '0': 751 | 'name': 'punctuation.section.array.end.ruby' 752 | 'name': 'constant.other.symbol.interpolated.ruby' 753 | 'patterns': [ 754 | { 755 | 'include': '#interpolated_ruby' 756 | } 757 | { 758 | 'include': '#escaped_char' 759 | } 760 | ] 761 | } 762 | { 763 | 'begin': '%i\\[' 764 | 'beginCaptures': 765 | '0': 766 | 'name': 'punctuation.section.array.begin.ruby' 767 | 'end': ']' 768 | 'endCaptures': 769 | '0': 770 | 'name': 'punctuation.section.array.end.ruby' 771 | 'name': 'constant.other.symbol.ruby' 772 | 'patterns': [ 773 | { 774 | 'match': '\\\\]|\\\\\\\\' 775 | 'name': 'constant.character.escape.ruby' 776 | } 777 | { 778 | 'include': '#nest_brackets' 779 | } 780 | ] 781 | } 782 | { 783 | 'begin': '%i\\(' 784 | 'beginCaptures': 785 | '0': 786 | 'name': 'punctuation.section.array.begin.ruby' 787 | 'end': '\\)' 788 | 'endCaptures': 789 | '0': 790 | 'name': 'punctuation.section.array.end.ruby' 791 | 'name': 'constant.other.symbol.ruby' 792 | 'patterns': [ 793 | { 794 | 'match': '\\\\\\)|\\\\\\\\' 795 | 'name': 'constant.character.escape.ruby' 796 | } 797 | { 798 | 'include': '#nest_parens' 799 | } 800 | ] 801 | } 802 | { 803 | 'begin': '%i<' 804 | 'beginCaptures': 805 | '0': 806 | 'name': 'punctuation.section.array.begin.ruby' 807 | 'end': '>' 808 | 'endCaptures': 809 | '0': 810 | 'name': 'punctuation.section.array.end.ruby' 811 | 'name': 'constant.other.symbol.ruby' 812 | 'patterns': [ 813 | { 814 | 'match': '\\\\>|\\\\\\\\' 815 | 'name': 'constant.character.escape.ruby' 816 | } 817 | { 818 | 'include': '#nest_ltgt' 819 | } 820 | ] 821 | } 822 | { 823 | 'begin': '%i{' 824 | 'beginCaptures': 825 | '0': 826 | 'name': 'punctuation.section.array.begin.ruby' 827 | 'end': '}' 828 | 'endCaptures': 829 | '0': 830 | 'name': 'punctuation.section.array.end.ruby' 831 | 'name': 'constant.other.symbol.ruby' 832 | 'patterns': [ 833 | { 834 | 'match': '\\\\}|\\\\\\\\' 835 | 'name': 'constant.character.escape.ruby' 836 | } 837 | { 838 | 'include': '#nest_curly' 839 | } 840 | ] 841 | } 842 | { 843 | 'begin': '%i([^\\w])' 844 | 'beginCaptures': 845 | '0': 846 | 'name': 'punctuation.section.array.begin.ruby' 847 | 'end': '\\1' 848 | 'endCaptures': 849 | '0': 850 | 'name': 'punctuation.section.array.end.ruby' 851 | 'name': 'constant.other.symbol.ruby' 852 | 'patterns': [ 853 | { 854 | 'comment': 'Cant be named because its not necessarily an escape.' 855 | 'match': '\\\\.' 856 | } 857 | ] 858 | } 859 | { 860 | 'begin': '%W\\[' 861 | 'beginCaptures': 862 | '0': 863 | 'name': 'punctuation.section.array.begin.ruby' 864 | 'end': ']' 865 | 'endCaptures': 866 | '0': 867 | 'name': 'punctuation.section.array.end.ruby' 868 | 'name': 'string.quoted.other.interpolated.ruby' 869 | 'patterns': [ 870 | { 871 | 'include': '#interpolated_ruby' 872 | } 873 | { 874 | 'include': '#escaped_char' 875 | } 876 | { 877 | 'include': '#nest_brackets_i' 878 | } 879 | ] 880 | } 881 | { 882 | 'begin': '%W\\(' 883 | 'beginCaptures': 884 | '0': 885 | 'name': 'punctuation.section.array.begin.ruby' 886 | 'end': '\\)' 887 | 'endCaptures': 888 | '0': 889 | 'name': 'punctuation.section.array.end.ruby' 890 | 'name': 'string.quoted.other.interpolated.ruby' 891 | 'patterns': [ 892 | { 893 | 'include': '#interpolated_ruby' 894 | } 895 | { 896 | 'include': '#escaped_char' 897 | } 898 | { 899 | 'include': '#nest_parens_i' 900 | } 901 | ] 902 | } 903 | { 904 | 'begin': '%W<' 905 | 'beginCaptures': 906 | '0': 907 | 'name': 'punctuation.section.array.begin.ruby' 908 | 'end': '>' 909 | 'endCaptures': 910 | '0': 911 | 'name': 'punctuation.section.array.end.ruby' 912 | 'name': 'string.quoted.other.interpolated.ruby' 913 | 'patterns': [ 914 | { 915 | 'include': '#interpolated_ruby' 916 | } 917 | { 918 | 'include': '#escaped_char' 919 | } 920 | { 921 | 'include': '#nest_ltgt_i' 922 | } 923 | ] 924 | } 925 | { 926 | 'begin': '%W{' 927 | 'beginCaptures': 928 | '0': 929 | 'name': 'punctuation.section.array.begin.ruby' 930 | 'end': '}' 931 | 'endCaptures': 932 | '0': 933 | 'name': 'punctuation.section.array.end.ruby' 934 | 'name': 'string.quoted.other.interpolated.ruby' 935 | 'patterns': [ 936 | { 937 | 'include': '#interpolated_ruby' 938 | } 939 | { 940 | 'include': '#escaped_char' 941 | } 942 | { 943 | 'include': '#nest_curly_i' 944 | } 945 | ] 946 | } 947 | { 948 | 'begin': '%W([^\\w])' 949 | 'beginCaptures': 950 | '0': 951 | 'name': 'punctuation.section.array.begin.ruby' 952 | 'end': '\\1' 953 | 'endCaptures': 954 | '0': 955 | 'name': 'punctuation.section.array.end.ruby' 956 | 'name': 'string.quoted.other.interpolated.ruby' 957 | 'patterns': [ 958 | { 959 | 'include': '#interpolated_ruby' 960 | } 961 | { 962 | 'include': '#escaped_char' 963 | } 964 | ] 965 | } 966 | { 967 | 'begin': '%w\\[' 968 | 'beginCaptures': 969 | '0': 970 | 'name': 'punctuation.section.array.begin.ruby' 971 | 'end': ']' 972 | 'endCaptures': 973 | '0': 974 | 'name': 'punctuation.section.array.end.ruby' 975 | 'name': 'string.quoted.other.ruby' 976 | 'patterns': [ 977 | { 978 | 'match': '\\\\]|\\\\\\\\' 979 | 'name': 'constant.character.escape.ruby' 980 | } 981 | { 982 | 'include': '#nest_brackets' 983 | } 984 | ] 985 | } 986 | { 987 | 'begin': '%w\\(' 988 | 'beginCaptures': 989 | '0': 990 | 'name': 'punctuation.section.array.begin.ruby' 991 | 'end': '\\)' 992 | 'endCaptures': 993 | '0': 994 | 'name': 'punctuation.section.array.end.ruby' 995 | 'name': 'string.quoted.other.ruby' 996 | 'patterns': [ 997 | { 998 | 'match': '\\\\\\)|\\\\\\\\' 999 | 'name': 'constant.character.escape.ruby' 1000 | } 1001 | { 1002 | 'include': '#nest_parens' 1003 | } 1004 | ] 1005 | } 1006 | { 1007 | 'begin': '%w<' 1008 | 'beginCaptures': 1009 | '0': 1010 | 'name': 'punctuation.section.array.begin.ruby' 1011 | 'end': '>' 1012 | 'endCaptures': 1013 | '0': 1014 | 'name': 'punctuation.section.array.end.ruby' 1015 | 'name': 'string.quoted.other.ruby' 1016 | 'patterns': [ 1017 | { 1018 | 'match': '\\\\>|\\\\\\\\' 1019 | 'name': 'constant.character.escape.ruby' 1020 | } 1021 | { 1022 | 'include': '#nest_ltgt' 1023 | } 1024 | ] 1025 | } 1026 | { 1027 | 'begin': '%w{' 1028 | 'beginCaptures': 1029 | '0': 1030 | 'name': 'punctuation.section.array.begin.ruby' 1031 | 'end': '}' 1032 | 'endCaptures': 1033 | '0': 1034 | 'name': 'punctuation.section.array.end.ruby' 1035 | 'name': 'string.quoted.other.ruby' 1036 | 'patterns': [ 1037 | { 1038 | 'match': '\\\\}|\\\\\\\\' 1039 | 'name': 'constant.character.escape.ruby' 1040 | } 1041 | { 1042 | 'include': '#nest_curly' 1043 | } 1044 | ] 1045 | } 1046 | { 1047 | 'begin': '%w([^\\w])' 1048 | 'beginCaptures': 1049 | '0': 1050 | 'name': 'punctuation.section.array.begin.ruby' 1051 | 'end': '\\1' 1052 | 'endCaptures': 1053 | '0': 1054 | 'name': 'punctuation.section.array.end.ruby' 1055 | 'name': 'string.quoted.other.ruby' 1056 | 'patterns': [ 1057 | { 1058 | 'comment': 'Cant be named because its not necessarily an escape.' 1059 | 'match': '\\\\.' 1060 | } 1061 | ] 1062 | } 1063 | { 1064 | 'begin': '%[Qx]?\\(' 1065 | 'beginCaptures': 1066 | '0': 1067 | 'name': 'punctuation.definition.string.begin.ruby' 1068 | 'end': '\\)' 1069 | 'endCaptures': 1070 | '0': 1071 | 'name': 'punctuation.definition.string.end.ruby' 1072 | 'name': 'string.quoted.other.interpolated.ruby' 1073 | 'patterns': [ 1074 | { 1075 | 'include': '#interpolated_ruby' 1076 | } 1077 | { 1078 | 'include': '#escaped_char' 1079 | } 1080 | { 1081 | 'include': '#nest_parens_i' 1082 | } 1083 | ] 1084 | } 1085 | { 1086 | 'begin': '%[Qx]?\\[' 1087 | 'beginCaptures': 1088 | '0': 1089 | 'name': 'punctuation.definition.string.begin.ruby' 1090 | 'end': ']' 1091 | 'endCaptures': 1092 | '0': 1093 | 'name': 'punctuation.definition.string.end.ruby' 1094 | 'name': 'string.quoted.other.interpolated.ruby' 1095 | 'patterns': [ 1096 | { 1097 | 'include': '#interpolated_ruby' 1098 | } 1099 | { 1100 | 'include': '#escaped_char' 1101 | } 1102 | { 1103 | 'include': '#nest_brackets_i' 1104 | } 1105 | ] 1106 | } 1107 | { 1108 | 'begin': '%[Qx]?{' 1109 | 'beginCaptures': 1110 | '0': 1111 | 'name': 'punctuation.definition.string.begin.ruby' 1112 | 'end': '}' 1113 | 'endCaptures': 1114 | '0': 1115 | 'name': 'punctuation.definition.string.end.ruby' 1116 | 'name': 'string.quoted.other.interpolated.ruby' 1117 | 'patterns': [ 1118 | { 1119 | 'include': '#interpolated_ruby' 1120 | } 1121 | { 1122 | 'include': '#escaped_char' 1123 | } 1124 | { 1125 | 'include': '#nest_curly_i' 1126 | } 1127 | ] 1128 | } 1129 | { 1130 | 'begin': '%[Qx]?<' 1131 | 'beginCaptures': 1132 | '0': 1133 | 'name': 'punctuation.definition.string.begin.ruby' 1134 | 'end': '>' 1135 | 'endCaptures': 1136 | '0': 1137 | 'name': 'punctuation.definition.string.end.ruby' 1138 | 'name': 'string.quoted.other.interpolated.ruby' 1139 | 'patterns': [ 1140 | { 1141 | 'include': '#interpolated_ruby' 1142 | } 1143 | { 1144 | 'include': '#escaped_char' 1145 | } 1146 | { 1147 | 'include': '#nest_ltgt_i' 1148 | } 1149 | ] 1150 | } 1151 | { 1152 | 'begin': '%[Qx]([^\\w])' 1153 | 'beginCaptures': 1154 | '0': 1155 | 'name': 'punctuation.definition.string.begin.ruby' 1156 | 'end': '\\1' 1157 | 'endCaptures': 1158 | '0': 1159 | 'name': 'punctuation.definition.string.end.ruby' 1160 | 'name': 'string.quoted.other.interpolated.ruby' 1161 | 'patterns': [ 1162 | { 1163 | 'include': '#interpolated_ruby' 1164 | } 1165 | { 1166 | 'include': '#escaped_char' 1167 | } 1168 | ] 1169 | } 1170 | { 1171 | 'begin': '%([^\\w\\s=])' 1172 | 'beginCaptures': 1173 | '0': 1174 | 'name': 'punctuation.definition.string.begin.ruby' 1175 | 'end': '\\1' 1176 | 'endCaptures': 1177 | '0': 1178 | 'name': 'punctuation.definition.string.end.ruby' 1179 | 'name': 'string.quoted.other.interpolated.ruby' 1180 | 'patterns': [ 1181 | { 1182 | 'include': '#interpolated_ruby' 1183 | } 1184 | { 1185 | 'include': '#escaped_char' 1186 | } 1187 | ] 1188 | } 1189 | { 1190 | 'begin': '%q\\(' 1191 | 'beginCaptures': 1192 | '0': 1193 | 'name': 'punctuation.definition.string.begin.ruby' 1194 | 'end': '\\)' 1195 | 'endCaptures': 1196 | '0': 1197 | 'name': 'punctuation.definition.string.end.ruby' 1198 | 'name': 'string.quoted.other.ruby' 1199 | 'patterns': [ 1200 | { 1201 | 'match': '\\\\\\)|\\\\\\\\' 1202 | 'name': 'constant.character.escape.ruby' 1203 | } 1204 | { 1205 | 'include': '#nest_parens' 1206 | } 1207 | ] 1208 | } 1209 | { 1210 | 'begin': '%q<' 1211 | 'beginCaptures': 1212 | '0': 1213 | 'name': 'punctuation.definition.string.begin.ruby' 1214 | 'end': '>' 1215 | 'endCaptures': 1216 | '0': 1217 | 'name': 'punctuation.definition.string.end.ruby' 1218 | 'name': 'string.quoted.other.ruby' 1219 | 'patterns': [ 1220 | { 1221 | 'match': '\\\\>|\\\\\\\\' 1222 | 'name': 'constant.character.escape.ruby' 1223 | } 1224 | { 1225 | 'include': '#nest_ltgt' 1226 | } 1227 | ] 1228 | } 1229 | { 1230 | 'begin': '%q\\[' 1231 | 'beginCaptures': 1232 | '0': 1233 | 'name': 'punctuation.definition.string.begin.ruby' 1234 | 'end': ']' 1235 | 'endCaptures': 1236 | '0': 1237 | 'name': 'punctuation.definition.string.end.ruby' 1238 | 'name': 'string.quoted.other.ruby' 1239 | 'patterns': [ 1240 | { 1241 | 'match': '\\\\]|\\\\\\\\' 1242 | 'name': 'constant.character.escape.ruby' 1243 | } 1244 | { 1245 | 'include': '#nest_brackets' 1246 | } 1247 | ] 1248 | } 1249 | { 1250 | 'begin': '%q{' 1251 | 'beginCaptures': 1252 | '0': 1253 | 'name': 'punctuation.definition.string.begin.ruby' 1254 | 'end': '}' 1255 | 'endCaptures': 1256 | '0': 1257 | 'name': 'punctuation.definition.string.end.ruby' 1258 | 'name': 'string.quoted.other.ruby' 1259 | 'patterns': [ 1260 | { 1261 | 'match': '\\\\}|\\\\\\\\' 1262 | 'name': 'constant.character.escape.ruby' 1263 | } 1264 | { 1265 | 'include': '#nest_curly' 1266 | } 1267 | ] 1268 | } 1269 | { 1270 | 'begin': '%q([^\\w])' 1271 | 'beginCaptures': 1272 | '0': 1273 | 'name': 'punctuation.definition.string.begin.ruby' 1274 | 'end': '\\1' 1275 | 'endCaptures': 1276 | '0': 1277 | 'name': 'punctuation.definition.string.end.ruby' 1278 | 'name': 'string.quoted.other.ruby' 1279 | 'patterns': [ 1280 | { 1281 | 'comment': 'Cant be named because its not necessarily an escape.' 1282 | 'match': '\\\\.' 1283 | } 1284 | ] 1285 | } 1286 | { 1287 | 'begin': '%s\\(' 1288 | 'beginCaptures': 1289 | '0': 1290 | 'name': 'punctuation.definition.symbol.begin.ruby' 1291 | 'end': '\\)' 1292 | 'endCaptures': 1293 | '0': 1294 | 'name': 'punctuation.definition.symbol.end.ruby' 1295 | 'name': 'constant.other.symbol.ruby' 1296 | 'patterns': [ 1297 | { 1298 | 'match': '\\\\\\)|\\\\\\\\' 1299 | 'name': 'constant.character.escape.ruby' 1300 | } 1301 | { 1302 | 'include': '#nest_parens' 1303 | } 1304 | ] 1305 | } 1306 | { 1307 | 'begin': '%s<' 1308 | 'beginCaptures': 1309 | '0': 1310 | 'name': 'punctuation.definition.symbol.begin.ruby' 1311 | 'end': '>' 1312 | 'endCaptures': 1313 | '0': 1314 | 'name': 'punctuation.definition.symbol.end.ruby' 1315 | 'name': 'constant.other.symbol.ruby' 1316 | 'patterns': [ 1317 | { 1318 | 'match': '\\\\>|\\\\\\\\' 1319 | 'name': 'constant.character.escape.ruby' 1320 | } 1321 | { 1322 | 'include': '#nest_ltgt' 1323 | } 1324 | ] 1325 | } 1326 | { 1327 | 'begin': '%s\\[' 1328 | 'beginCaptures': 1329 | '0': 1330 | 'name': 'punctuation.definition.symbol.begin.ruby' 1331 | 'end': ']' 1332 | 'endCaptures': 1333 | '0': 1334 | 'name': 'punctuation.definition.symbol.end.ruby' 1335 | 'name': 'constant.other.symbol.ruby' 1336 | 'patterns': [ 1337 | { 1338 | 'match': '\\\\]|\\\\\\\\' 1339 | 'name': 'constant.character.escape.ruby' 1340 | } 1341 | { 1342 | 'include': '#nest_brackets' 1343 | } 1344 | ] 1345 | } 1346 | { 1347 | 'begin': '%s{' 1348 | 'beginCaptures': 1349 | '0': 1350 | 'name': 'punctuation.definition.symbol.begin.ruby' 1351 | 'end': '}' 1352 | 'endCaptures': 1353 | '0': 1354 | 'name': 'punctuation.definition.symbol.end.ruby' 1355 | 'name': 'constant.other.symbol.ruby' 1356 | 'patterns': [ 1357 | { 1358 | 'match': '\\\\}|\\\\\\\\' 1359 | 'name': 'constant.character.escape.ruby' 1360 | } 1361 | { 1362 | 'include': '#nest_curly' 1363 | } 1364 | ] 1365 | } 1366 | { 1367 | 'begin': '%s([^\\w])' 1368 | 'beginCaptures': 1369 | '0': 1370 | 'name': 'punctuation.definition.symbol.begin.ruby' 1371 | 'end': '\\1' 1372 | 'endCaptures': 1373 | '0': 1374 | 'name': 'punctuation.definition.symbol.end.ruby' 1375 | 'name': 'constant.other.symbol.ruby' 1376 | 'patterns': [ 1377 | { 1378 | 'comment': 'Cant be named because its not necessarily an escape.' 1379 | 'match': '\\\\.' 1380 | } 1381 | ] 1382 | } 1383 | { 1384 | 'captures': 1385 | '1': 1386 | 'name': 'punctuation.definition.constant.ruby' 1387 | 'comment': 'symbols' 1388 | 'match': '''(?x) 1389 | (? 1391 | [$a-zA-Z_]\\w*(?>[?!]|=(?![>=]))? 1392 | | 1393 | ===?|<=>|>[>=]?|<[<=]?|[%&`/\\|]|\\*\\*?|=?~|[-+]@?|\\[]=? 1394 | | 1395 | @@?[a-zA-Z_]\\w* 1396 | ) 1397 | ''' 1398 | 'name': 'constant.other.symbol.ruby' 1399 | } 1400 | { 1401 | 'begin': '^=begin' 1402 | 'captures': 1403 | '0': 1404 | 'name': 'punctuation.definition.comment.ruby' 1405 | 'comment': 'multiline comments' 1406 | 'end': '^=end' 1407 | 'name': 'comment.block.documentation.ruby' 1408 | } 1409 | { 1410 | 'include': '#yard' 1411 | } 1412 | { 1413 | 'begin': '(^[ \\t]+)?(?=#)' 1414 | 'beginCaptures': 1415 | '1': 1416 | 'name': 'punctuation.whitespace.comment.leading.ruby' 1417 | 'end': '(?!\\G)' 1418 | 'patterns': [ 1419 | { 1420 | 'begin': '#' 1421 | 'beginCaptures': 1422 | '0': 1423 | 'name': 'punctuation.definition.comment.ruby' 1424 | 'end': '\\n' 1425 | 'name': 'comment.line.number-sign.ruby' 1426 | } 1427 | ] 1428 | } 1429 | { 1430 | 'comment': '\n\t\t\tmatches questionmark-letters.\n\n\t\t\texamples (1st alternation = hex):\n\t\t\t?\\x1 ?\\x61\n\n\t\t\texamples (2nd alternation = octal):\n\t\t\t?\\0 ?\\07 ?\\017\n\n\t\t\texamples (3rd alternation = escaped):\n\t\t\t?\\n ?\\b\n\n\t\t\texamples (4th alternation = meta-ctrl):\n\t\t\t?\\C-a ?\\M-a ?\\C-\\M-\\C-\\M-a\n\n\t\t\texamples (4th alternation = normal):\n\t\t\t?a ?A ?0 \n\t\t\t?* ?" ?( \n\t\t\t?. ?#\n\t\t\t\n\t\t\t\n\t\t\tthe negative lookbehind prevents against matching\n\t\t\tp(42.tainted?)\n\t\t\t' 1431 | 'match': '(?<<[-~](["\'`]?)((?:[_\\w]+_|)HTML)\\b\\1))' 1457 | 'comment': 'Heredoc with embedded html' 1458 | 'end': '(?!\\G)' 1459 | 'name': 'meta.embedded.block.html' 1460 | 'patterns': [ 1461 | { 1462 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)HTML)\\b\\1)' 1463 | 'beginCaptures': 1464 | '0': 1465 | 'name': 'punctuation.definition.string.begin.ruby' 1466 | 'contentName': 'text.html' 1467 | 'end': '^\\s*\\2$\\n?' 1468 | 'endCaptures': 1469 | '0': 1470 | 'name': 'punctuation.definition.string.end.ruby' 1471 | 'name': 'string.unquoted.heredoc.ruby' 1472 | 'patterns': [ 1473 | { 1474 | 'include': '#heredoc' 1475 | } 1476 | { 1477 | 'include': '#interpolated_ruby' 1478 | } 1479 | { 1480 | 'include': 'text.html.basic' 1481 | } 1482 | { 1483 | 'include': '#escaped_char' 1484 | } 1485 | ] 1486 | } 1487 | ] 1488 | } 1489 | { 1490 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)XML)\\b\\1))' 1491 | 'comment': 'Heredoc with embedded xml' 1492 | 'end': '(?!\\G)' 1493 | 'name': 'meta.embedded.block.xml' 1494 | 'patterns': [ 1495 | { 1496 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)XML)\\b\\1)' 1497 | 'beginCaptures': 1498 | '0': 1499 | 'name': 'punctuation.definition.string.begin.ruby' 1500 | 'contentName': 'text.xml' 1501 | 'end': '^\\s*\\2$\\n?' 1502 | 'endCaptures': 1503 | '0': 1504 | 'name': 'punctuation.definition.string.end.ruby' 1505 | 'name': 'string.unquoted.heredoc.ruby' 1506 | 'patterns': [ 1507 | { 1508 | 'include': '#heredoc' 1509 | } 1510 | { 1511 | 'include': '#interpolated_ruby' 1512 | } 1513 | { 1514 | 'include': 'text.xml' 1515 | } 1516 | { 1517 | 'include': '#escaped_char' 1518 | } 1519 | ] 1520 | } 1521 | ] 1522 | } 1523 | { 1524 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)SQL)\\b\\1))' 1525 | 'comment': 'Heredoc with embedded sql' 1526 | 'end': '(?!\\G)' 1527 | 'name': 'meta.embedded.block.sql' 1528 | 'patterns': [ 1529 | { 1530 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)SQL)\\b\\1)' 1531 | 'beginCaptures': 1532 | '0': 1533 | 'name': 'punctuation.definition.string.begin.ruby' 1534 | 'contentName': 'source.sql' 1535 | 'end': '^\\s*\\2$\\n?' 1536 | 'endCaptures': 1537 | '0': 1538 | 'name': 'punctuation.definition.string.end.ruby' 1539 | 'name': 'string.unquoted.heredoc.ruby' 1540 | 'patterns': [ 1541 | { 1542 | 'include': '#heredoc' 1543 | } 1544 | { 1545 | 'include': '#interpolated_ruby' 1546 | } 1547 | { 1548 | 'include': 'source.sql' 1549 | } 1550 | { 1551 | 'include': '#escaped_char' 1552 | } 1553 | ] 1554 | } 1555 | ] 1556 | } 1557 | { 1558 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)GRAPHQL)\\b\\1))' 1559 | 'comment': 'Heredoc with embedded GraphQL' 1560 | 'end': '(?!\\G)' 1561 | 'name': 'meta.embedded.block.graphql' 1562 | 'patterns': [ 1563 | { 1564 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)GRAPHQL)\\b\\1)' 1565 | 'beginCaptures': 1566 | '0': 1567 | 'name': 'punctuation.definition.string.begin.ruby' 1568 | 'contentName': 'source.graphql' 1569 | 'end': '^\\s*\\2$\\n?' 1570 | 'endCaptures': 1571 | '0': 1572 | 'name': 'punctuation.definition.string.end.ruby' 1573 | 'name': 'string.unquoted.heredoc.ruby' 1574 | 'patterns': [ 1575 | { 1576 | 'include': '#heredoc' 1577 | } 1578 | { 1579 | 'include': '#interpolated_ruby' 1580 | } 1581 | { 1582 | 'include': 'source.graphql' 1583 | } 1584 | { 1585 | 'include': '#escaped_char' 1586 | } 1587 | ] 1588 | } 1589 | ] 1590 | } 1591 | { 1592 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)CSS)\\b\\1))' 1593 | 'comment': 'Heredoc with embedded css' 1594 | 'end': '(?!\\G)' 1595 | 'name': 'meta.embedded.block.css' 1596 | 'patterns': [ 1597 | { 1598 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)CSS)\\b\\1)' 1599 | 'beginCaptures': 1600 | '0': 1601 | 'name': 'punctuation.definition.string.begin.ruby' 1602 | 'contentName': 'source.css' 1603 | 'end': '^\\s*\\2$\\n?' 1604 | 'endCaptures': 1605 | '0': 1606 | 'name': 'punctuation.definition.string.end.ruby' 1607 | 'name': 'string.unquoted.heredoc.ruby' 1608 | 'patterns': [ 1609 | { 1610 | 'include': '#heredoc' 1611 | } 1612 | { 1613 | 'include': '#interpolated_ruby' 1614 | } 1615 | { 1616 | 'include': 'source.css' 1617 | } 1618 | { 1619 | 'include': '#escaped_char' 1620 | } 1621 | ] 1622 | } 1623 | ] 1624 | } 1625 | { 1626 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)CPP)\\b\\1))' 1627 | 'comment': 'Heredoc with embedded c++' 1628 | 'end': '(?!\\G)' 1629 | 'name': 'meta.embedded.block.cpp' 1630 | 'patterns': [ 1631 | { 1632 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)CPP)\\b\\1)' 1633 | 'beginCaptures': 1634 | '0': 1635 | 'name': 'punctuation.definition.string.begin.ruby' 1636 | 'contentName': 'source.cpp' 1637 | 'end': '^\\s*\\2$\\n?' 1638 | 'endCaptures': 1639 | '0': 1640 | 'name': 'punctuation.definition.string.end.ruby' 1641 | 'name': 'string.unquoted.heredoc.ruby' 1642 | 'patterns': [ 1643 | { 1644 | 'include': '#heredoc' 1645 | } 1646 | { 1647 | 'include': '#interpolated_ruby' 1648 | } 1649 | { 1650 | 'include': 'source.cpp' 1651 | } 1652 | { 1653 | 'include': '#escaped_char' 1654 | } 1655 | ] 1656 | } 1657 | ] 1658 | } 1659 | { 1660 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)C)\\b\\1))' 1661 | 'comment': 'Heredoc with embedded c' 1662 | 'end': '(?!\\G)' 1663 | 'name': 'meta.embedded.block.c' 1664 | 'patterns': [ 1665 | { 1666 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)C)\\b\\1)' 1667 | 'beginCaptures': 1668 | '0': 1669 | 'name': 'punctuation.definition.string.begin.ruby' 1670 | 'contentName': 'source.c' 1671 | 'end': '^\\s*\\2$\\n?' 1672 | 'endCaptures': 1673 | '0': 1674 | 'name': 'punctuation.definition.string.end.ruby' 1675 | 'name': 'string.unquoted.heredoc.ruby' 1676 | 'patterns': [ 1677 | { 1678 | 'include': '#heredoc' 1679 | } 1680 | { 1681 | 'include': '#interpolated_ruby' 1682 | } 1683 | { 1684 | 'include': 'source.c' 1685 | } 1686 | { 1687 | 'include': '#escaped_char' 1688 | } 1689 | ] 1690 | } 1691 | ] 1692 | } 1693 | { 1694 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)(?:JS|JAVASCRIPT))\\b\\1))' 1695 | 'comment': 'Heredoc with embedded javascript' 1696 | 'end': '(?!\\G)' 1697 | 'name': 'meta.embedded.block.js' 1698 | 'patterns': [ 1699 | { 1700 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)(?:JS|JAVASCRIPT))\\b\\1)' 1701 | 'beginCaptures': 1702 | '0': 1703 | 'name': 'punctuation.definition.string.begin.ruby' 1704 | 'contentName': 'source.js' 1705 | 'end': '^\\s*\\2$\\n?' 1706 | 'endCaptures': 1707 | '0': 1708 | 'name': 'punctuation.definition.string.end.ruby' 1709 | 'name': 'string.unquoted.heredoc.ruby' 1710 | 'patterns': [ 1711 | { 1712 | 'include': '#heredoc' 1713 | } 1714 | { 1715 | 'include': '#interpolated_ruby' 1716 | } 1717 | { 1718 | 'include': 'source.js' 1719 | } 1720 | { 1721 | 'include': '#escaped_char' 1722 | } 1723 | ] 1724 | } 1725 | ] 1726 | } 1727 | { 1728 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)JQUERY)\\b\\1))' 1729 | 'comment': 'Heredoc with embedded jQuery javascript' 1730 | 'end': '(?!\\G)' 1731 | 'name': 'meta.embedded.block.js.jquery' 1732 | 'patterns': [ 1733 | { 1734 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)JQUERY)\\b\\1)' 1735 | 'beginCaptures': 1736 | '0': 1737 | 'name': 'punctuation.definition.string.begin.ruby' 1738 | 'contentName': 'source.js.jquery' 1739 | 'end': '^\\s*\\2$\\n?' 1740 | 'endCaptures': 1741 | '0': 1742 | 'name': 'punctuation.definition.string.end.ruby' 1743 | 'name': 'string.unquoted.heredoc.ruby' 1744 | 'patterns': [ 1745 | { 1746 | 'include': '#heredoc' 1747 | } 1748 | { 1749 | 'include': '#interpolated_ruby' 1750 | } 1751 | { 1752 | 'include': 'source.js.jquery' 1753 | } 1754 | { 1755 | 'include': '#escaped_char' 1756 | } 1757 | ] 1758 | } 1759 | ] 1760 | } 1761 | { 1762 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)(?:SH|SHELL))\\b\\1))' 1763 | 'comment': 'Heredoc with embedded shell' 1764 | 'end': '(?!\\G)' 1765 | 'name': 'meta.embedded.block.shell' 1766 | 'patterns': [ 1767 | { 1768 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)(?:SH|SHELL))\\b\\1)' 1769 | 'beginCaptures': 1770 | '0': 1771 | 'name': 'punctuation.definition.string.begin.ruby' 1772 | 'contentName': 'source.shell' 1773 | 'end': '^\\s*\\2$\\n?' 1774 | 'endCaptures': 1775 | '0': 1776 | 'name': 'punctuation.definition.string.end.ruby' 1777 | 'name': 'string.unquoted.heredoc.ruby' 1778 | 'patterns': [ 1779 | { 1780 | 'include': '#heredoc' 1781 | } 1782 | { 1783 | 'include': '#interpolated_ruby' 1784 | } 1785 | { 1786 | 'include': 'source.shell' 1787 | } 1788 | { 1789 | 'include': '#escaped_char' 1790 | } 1791 | ] 1792 | } 1793 | ] 1794 | } 1795 | { 1796 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)LUA)\\b\\1))' 1797 | 'comment': 'Heredoc with embedded lua' 1798 | 'end': '(?!\\G)' 1799 | 'name': 'meta.embedded.block.lua' 1800 | 'patterns': [ 1801 | { 1802 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)LUA)\\b\\1)' 1803 | 'beginCaptures': 1804 | '0': 1805 | 'name': 'punctuation.definition.string.begin.ruby' 1806 | 'contentName': 'source.lua' 1807 | 'end': '^\\s*\\2$\\n?' 1808 | 'endCaptures': 1809 | '0': 1810 | 'name': 'punctuation.definition.string.end.ruby' 1811 | 'name': 'string.unquoted.heredoc.ruby' 1812 | 'patterns': [ 1813 | { 1814 | 'include': '#heredoc' 1815 | } 1816 | { 1817 | 'include': '#interpolated_ruby' 1818 | } 1819 | { 1820 | 'include': 'source.lua' 1821 | } 1822 | { 1823 | 'include': '#escaped_char' 1824 | } 1825 | ] 1826 | } 1827 | ] 1828 | } 1829 | { 1830 | 'begin': '(?=(?><<[-~](["\'`]?)((?:[_\\w]+_|)RUBY)\\b\\1))' 1831 | 'comment': 'Heredoc with embedded ruby' 1832 | 'end': '(?!\\G)' 1833 | 'name': 'meta.embedded.block.ruby' 1834 | 'patterns': [ 1835 | { 1836 | 'begin': '(?><<[-~](["\'`]?)((?:[_\\w]+_|)RUBY)\\b\\1)' 1837 | 'beginCaptures': 1838 | '0': 1839 | 'name': 'punctuation.definition.string.begin.ruby' 1840 | 'contentName': 'source.ruby' 1841 | 'end': '^\\s*\\2$\\n?' 1842 | 'endCaptures': 1843 | '0': 1844 | 'name': 'punctuation.definition.string.end.ruby' 1845 | 'name': 'string.unquoted.heredoc.ruby' 1846 | 'patterns': [ 1847 | { 1848 | 'include': '#heredoc' 1849 | } 1850 | { 1851 | 'include': '#interpolated_ruby' 1852 | } 1853 | { 1854 | 'include': 'source.ruby' 1855 | } 1856 | { 1857 | 'include': '#escaped_char' 1858 | } 1859 | ] 1860 | } 1861 | ] 1862 | } 1863 | { 1864 | 'begin': '(?>=\\s*<<(["\'`]?)(\\w+)\\1)' 1865 | 'beginCaptures': 1866 | '0': 1867 | 'name': 'punctuation.definition.string.begin.ruby' 1868 | 'end': '^\\2$' 1869 | 'endCaptures': 1870 | '0': 1871 | 'name': 'punctuation.definition.string.end.ruby' 1872 | 'name': 'string.unquoted.heredoc.ruby' 1873 | 'patterns': [ 1874 | { 1875 | 'include': '#heredoc' 1876 | } 1877 | { 1878 | 'include': '#interpolated_ruby' 1879 | } 1880 | { 1881 | 'include': '#escaped_char' 1882 | } 1883 | ] 1884 | } 1885 | { 1886 | 'begin': '(?>((<<[-~](["\'`]?)(\\w+)\\3,\\s?)*<<[-~](["\'`]?)(\\w+)\\5))' 1887 | 'beginCaptures': 1888 | '0': 1889 | 'name': 'punctuation.definition.string.begin.ruby' 1890 | 'comment': 'heredoc with multiple inputs and indented terminator' 1891 | 'end': '^\\s*\\6$' 1892 | 'endCaptures': 1893 | '0': 1894 | 'name': 'punctuation.definition.string.end.ruby' 1895 | 'name': 'string.unquoted.heredoc.ruby' 1896 | 'patterns': [ 1897 | { 1898 | 'include': '#heredoc' 1899 | } 1900 | { 1901 | 'include': '#interpolated_ruby' 1902 | } 1903 | { 1904 | 'include': '#escaped_char' 1905 | } 1906 | ] 1907 | } 1908 | { 1909 | 'begin': '(?<={|{\\s|[^A-Za-z0-9_]do|^do|[^A-Za-z0-9_]do\\s|^do\\s)(\\|)' 1910 | 'captures': 1911 | '1': 1912 | 'name': 'punctuation.separator.variable.ruby' 1913 | 'end': '(?' 1933 | 'name': 'support.function.kernel.arrow.ruby' 1934 | } 1935 | { 1936 | 'match': '<<=|%=|&{1,2}=|\\*=|\\*\\*=|\\+=|-=|\\^=|\\|{1,2}=|<<' 1937 | 'name': 'keyword.operator.assignment.augmented.ruby' 1938 | } 1939 | { 1940 | 'match': '<=>|<(?!<|=)|>(?!<|=|>)|<=|>=|===|==|=~|!=|!~|(?<=[ \\t])\\?' 1941 | 'name': 'keyword.operator.comparison.ruby' 1942 | } 1943 | { 1944 | 'match': '(?>' 1962 | 'name': 'keyword.operator.other.ruby' 1963 | } 1964 | { 1965 | 'match': '{' 1966 | 'name': 'punctuation.section.scope.begin.ruby' 1967 | } 1968 | { 1969 | 'match': '}' 1970 | 'name': 'punctuation.section.scope.end.ruby' 1971 | } 1972 | { 1973 | 'match': '\\[' 1974 | 'name': 'punctuation.section.array.begin.ruby' 1975 | } 1976 | { 1977 | 'match': ']' 1978 | 'name': 'punctuation.section.array.end.ruby' 1979 | } 1980 | { 1981 | 'match': '\\(|\\)' 1982 | 'name': 'punctuation.section.function.ruby' 1983 | } 1984 | ] 1985 | 'repository': 1986 | 'escaped_char': 1987 | 'match': '\\\\(?:[0-7]{1,3}|x[\\da-fA-F]{1,2}|.)' 1988 | 'name': 'constant.character.escape.ruby' 1989 | 'heredoc': 1990 | 'begin': '^<<[-~]?\\w+' 1991 | 'end': '$' 1992 | 'patterns': [ 1993 | { 1994 | 'include': '$self' 1995 | } 1996 | ] 1997 | 'interpolated_ruby': 1998 | 'patterns': [ 1999 | { 2000 | 'begin': '#{' 2001 | 'beginCaptures': 2002 | '0': 2003 | 'name': 'punctuation.section.embedded.begin.ruby' 2004 | 'contentName': 'source.ruby' 2005 | 'end': '}' 2006 | 'endCaptures': 2007 | '0': 2008 | 'name': 'punctuation.section.embedded.end.ruby' 2009 | 'name': 'meta.embedded.line.ruby' 2010 | 'patterns': [ 2011 | { 2012 | 'include': '#nest_curly_and_self' 2013 | } 2014 | { 2015 | 'include': '$self' 2016 | } 2017 | ] 2018 | } 2019 | { 2020 | 'captures': 2021 | '1': 2022 | 'name': 'punctuation.definition.variable.ruby' 2023 | 'match': '(#@)[a-zA-Z_]\\w*' 2024 | 'name': 'variable.other.readwrite.instance.ruby' 2025 | } 2026 | { 2027 | 'captures': 2028 | '1': 2029 | 'name': 'punctuation.definition.variable.ruby' 2030 | 'match': '(#@@)[a-zA-Z_]\\w*' 2031 | 'name': 'variable.other.readwrite.class.ruby' 2032 | } 2033 | { 2034 | 'captures': 2035 | '1': 2036 | 'name': 'punctuation.definition.variable.ruby' 2037 | 'match': '(#\\$)[a-zA-Z_]\\w*' 2038 | 'name': 'variable.other.readwrite.global.ruby' 2039 | } 2040 | ] 2041 | 'nest_brackets': 2042 | 'begin': '\\[' 2043 | 'captures': 2044 | '0': 2045 | 'name': 'punctuation.section.scope.ruby' 2046 | 'end': ']' 2047 | 'patterns': [ 2048 | { 2049 | 'include': '#nest_brackets' 2050 | } 2051 | ] 2052 | 'nest_brackets_i': 2053 | 'begin': '\\[' 2054 | 'captures': 2055 | '0': 2056 | 'name': 'punctuation.section.scope.ruby' 2057 | 'end': ']' 2058 | 'patterns': [ 2059 | { 2060 | 'include': '#interpolated_ruby' 2061 | } 2062 | { 2063 | 'include': '#escaped_char' 2064 | } 2065 | { 2066 | 'include': '#nest_brackets_i' 2067 | } 2068 | ] 2069 | 'nest_brackets_r': 2070 | 'begin': '\\[' 2071 | 'captures': 2072 | '0': 2073 | 'name': 'punctuation.section.scope.ruby' 2074 | 'end': ']' 2075 | 'patterns': [ 2076 | { 2077 | 'include': '#regex_sub' 2078 | } 2079 | { 2080 | 'include': '#nest_brackets_r' 2081 | } 2082 | ] 2083 | 'nest_curly': 2084 | 'begin': '{' 2085 | 'captures': 2086 | '0': 2087 | 'name': 'punctuation.section.scope.ruby' 2088 | 'end': '}' 2089 | 'patterns': [ 2090 | { 2091 | 'include': '#nest_curly' 2092 | } 2093 | ] 2094 | 'nest_curly_and_self': 2095 | 'patterns': [ 2096 | { 2097 | 'begin': '{' 2098 | 'captures': 2099 | '0': 2100 | 'name': 'punctuation.section.scope.ruby' 2101 | 'end': '}' 2102 | 'patterns': [ 2103 | { 2104 | 'include': '#nest_curly_and_self' 2105 | } 2106 | ] 2107 | } 2108 | { 2109 | 'include': '$self' 2110 | } 2111 | ] 2112 | 'nest_curly_i': 2113 | 'begin': '{' 2114 | 'captures': 2115 | '0': 2116 | 'name': 'punctuation.section.scope.ruby' 2117 | 'end': '}' 2118 | 'patterns': [ 2119 | { 2120 | 'include': '#interpolated_ruby' 2121 | } 2122 | { 2123 | 'include': '#escaped_char' 2124 | } 2125 | { 2126 | 'include': '#nest_curly_i' 2127 | } 2128 | ] 2129 | 'nest_curly_r': 2130 | 'begin': '{' 2131 | 'captures': 2132 | '0': 2133 | 'name': 'punctuation.section.scope.ruby' 2134 | 'end': '}' 2135 | 'patterns': [ 2136 | { 2137 | 'include': '#regex_sub' 2138 | } 2139 | { 2140 | 'include': '#nest_curly_r' 2141 | } 2142 | ] 2143 | 'nest_ltgt': 2144 | 'begin': '<' 2145 | 'captures': 2146 | '0': 2147 | 'name': 'punctuation.section.scope.ruby' 2148 | 'end': '>' 2149 | 'patterns': [ 2150 | { 2151 | 'include': '#nest_ltgt' 2152 | } 2153 | ] 2154 | 'nest_ltgt_i': 2155 | 'begin': '<' 2156 | 'captures': 2157 | '0': 2158 | 'name': 'punctuation.section.scope.ruby' 2159 | 'end': '>' 2160 | 'patterns': [ 2161 | { 2162 | 'include': '#interpolated_ruby' 2163 | } 2164 | { 2165 | 'include': '#escaped_char' 2166 | } 2167 | { 2168 | 'include': '#nest_ltgt_i' 2169 | } 2170 | ] 2171 | 'nest_ltgt_r': 2172 | 'begin': '<' 2173 | 'captures': 2174 | '0': 2175 | 'name': 'punctuation.section.scope.ruby' 2176 | 'end': '>' 2177 | 'patterns': [ 2178 | { 2179 | 'include': '#regex_sub' 2180 | } 2181 | { 2182 | 'include': '#nest_ltgt_r' 2183 | } 2184 | ] 2185 | 'nest_parens': 2186 | 'begin': '\\(' 2187 | 'captures': 2188 | '0': 2189 | 'name': 'punctuation.section.scope.ruby' 2190 | 'end': '\\)' 2191 | 'patterns': [ 2192 | { 2193 | 'include': '#nest_parens' 2194 | } 2195 | ] 2196 | 'nest_parens_i': 2197 | 'begin': '\\(' 2198 | 'captures': 2199 | '0': 2200 | 'name': 'punctuation.section.scope.ruby' 2201 | 'end': '\\)' 2202 | 'patterns': [ 2203 | { 2204 | 'include': '#interpolated_ruby' 2205 | } 2206 | { 2207 | 'include': '#escaped_char' 2208 | } 2209 | { 2210 | 'include': '#nest_parens_i' 2211 | } 2212 | ] 2213 | 'nest_parens_r': 2214 | 'begin': '\\(' 2215 | 'captures': 2216 | '0': 2217 | 'name': 'punctuation.section.scope.ruby' 2218 | 'end': '\\)' 2219 | 'patterns': [ 2220 | { 2221 | 'include': '#regex_sub' 2222 | } 2223 | { 2224 | 'include': '#nest_parens_r' 2225 | } 2226 | ] 2227 | 'regex_sub': 2228 | 'patterns': [ 2229 | { 2230 | 'include': '#interpolated_ruby' 2231 | } 2232 | { 2233 | 'include': '#escaped_char' 2234 | } 2235 | { 2236 | 'captures': 2237 | '1': 2238 | 'name': 'punctuation.definition.arbitrary-repetition.ruby' 2239 | '3': 2240 | 'name': 'punctuation.definition.arbitrary-repetition.ruby' 2241 | 'match': '({)\\d+(,\\d+)?(})' 2242 | 'name': 'string.regexp.arbitrary-repetition.ruby' 2243 | } 2244 | { 2245 | 'begin': '\\[(?:\\^?])?' 2246 | 'captures': 2247 | '0': 2248 | 'name': 'punctuation.definition.character-class.ruby' 2249 | 'end': ']' 2250 | 'name': 'string.regexp.character-class.ruby' 2251 | 'patterns': [ 2252 | { 2253 | 'include': '#escaped_char' 2254 | } 2255 | ] 2256 | } 2257 | { 2258 | 'begin': '\\(\\?#' 2259 | 'beginCaptures': 2260 | '0': 2261 | 'name': 'punctuation.definition.comment.begin.ruby' 2262 | 'end': '\\)' 2263 | 'endCaptures': 2264 | '0': 2265 | 'name': 'punctuation.definition.comment.end.ruby' 2266 | 'name': 'comment.line.number-sign.ruby' 2267 | 'patterns': [ 2268 | { 2269 | 'include': '#escaped_char' 2270 | } 2271 | ] 2272 | } 2273 | { 2274 | 'begin': '\\(' 2275 | 'captures': 2276 | '0': 2277 | 'name': 'punctuation.definition.group.ruby' 2278 | 'end': '\\)' 2279 | 'name': 'string.regexp.group.ruby' 2280 | 'patterns': [ 2281 | { 2282 | 'include': '#regex_sub' 2283 | } 2284 | ] 2285 | } 2286 | { 2287 | 'begin': '(?<=^|\\s)(#)\\s(?=[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$)' 2288 | 'beginCaptures': 2289 | '1': 2290 | 'name': 'punctuation.definition.comment.ruby' 2291 | 'comment': 'We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.' 2292 | 'end': '$\\n?' 2293 | 'endCaptures': 2294 | '0': 2295 | 'name': 'punctuation.definition.comment.ruby' 2296 | 'name': 'comment.line.number-sign.ruby' 2297 | } 2298 | ] 2299 | 'separators': 2300 | 'patterns': [ 2301 | { 2302 | 'match': '=>' 2303 | 'name': 'punctuation.separator.key-value.ruby' 2304 | } 2305 | { 2306 | 'match': ';' 2307 | 'name': 'punctuation.terminator.statement.ruby' 2308 | } 2309 | { 2310 | 'match': ',' 2311 | 'name': 'punctuation.separator.delimiter.ruby' 2312 | } 2313 | { 2314 | 'match': '(::)(?=\\s*[A-Z])' 2315 | 'captures': 2316 | '1': 2317 | 'name': 'punctuation.separator.namespace.ruby' 2318 | } 2319 | { 2320 | 'match': '&?\\.|::' 2321 | 'name': 'punctuation.separator.method.ruby' 2322 | } 2323 | { 2324 | 'match': ':' 2325 | 'name': 'punctuation.separator.other.ruby' 2326 | } 2327 | ] 2328 | 'yard': 2329 | 'patterns': [ 2330 | { 2331 | 'include': '#yard_comment' 2332 | } 2333 | { 2334 | 'include': '#yard_name_types' 2335 | } 2336 | { 2337 | 'include': '#yard_tag' 2338 | } 2339 | { 2340 | 'include': '#yard_types' 2341 | } 2342 | { 2343 | 'include': '#yard_directive' 2344 | } 2345 | ] 2346 | 'yard_comment': 2347 | 'comment': 'For YARD tags that follow the tag-comment pattern' 2348 | 'begin': '^(\\s*)(#)(\\s*)(@)(abstract|api|author|deprecated|example|macro|note|overload|since|todo|version)(?=\\s|$)' 2349 | 'beginCaptures': 2350 | '1': 2351 | 'name': '' 2352 | '2': 2353 | 'name': 'punctuation.definition.comment.ruby' 2354 | '3': 2355 | 'name': '' 2356 | '4': 2357 | 'name': 'comment.line.keyword.punctuation.yard.ruby' 2358 | '5': 2359 | 'name': 'comment.line.keyword.yard.ruby' 2360 | 'end': '^(?!\\s*#\\3\\s{2,})' 2361 | 'contentName': 'comment.line.string.yard.ruby' 2362 | 'name': 'comment.line.number-sign.ruby' 2363 | 'patterns': [ 2364 | { 2365 | 'include': '#yard' 2366 | } 2367 | { 2368 | 'include': '#yard_continuation' 2369 | } 2370 | ] 2371 | 'yard_name_types': 2372 | 'comment': 'For YARD tags that follow the tag-name-types-comment pattern' 2373 | 'begin': '^(\\s*)(#)(\\s*)(@)(attr|attr_reader|attr_writer|option|param|see|yieldparam)(?=\\s)(\\s+([a-z_][a-zA-Z_]*))?(\\s+((\\[).+(])))?' 2374 | 'beginCaptures': 2375 | '1': 2376 | 'name': '' 2377 | '2': 2378 | 'name': 'punctuation.definition.comment.ruby' 2379 | '3': 2380 | 'name': '' 2381 | '4': 2382 | 'name': 'comment.line.keyword.punctuation.yard.ruby' 2383 | '5': 2384 | 'name': 'comment.line.keyword.yard.ruby' 2385 | '6': 2386 | 'name': 'comment.line.yard.ruby' 2387 | '7': 2388 | 'name': 'comment.line.parameter.yard.ruby' 2389 | '8': 2390 | 'name': 'comment.line.yard.ruby' 2391 | '9': 2392 | 'name': 'comment.line.type.yard.ruby' 2393 | '10': 2394 | 'name': 'comment.line.punctuation.yard.ruby' 2395 | '11': 2396 | 'name': 'comment.line.punctuation.yard.ruby' 2397 | 'end': '^(?!\\s*#\\3\\s{2,})' 2398 | 'contentName': 'comment.line.string.yard.ruby' 2399 | 'name': 'comment.line.number-sign.ruby' 2400 | 'patterns': [ 2401 | { 2402 | 'include': '#yard' 2403 | } 2404 | { 2405 | 'include': '#yard_continuation' 2406 | } 2407 | ] 2408 | 'yard_tag': 2409 | 'comment': 'For YARD tags that are just the tag' 2410 | 'match': '^(\\s*)(#)(\\s*)(@)(private)$' 2411 | 'captures': 2412 | '1': 2413 | 'name': '' 2414 | '2': 2415 | 'name': 'punctuation.definition.comment.ruby' 2416 | '3': 2417 | 'name': '' 2418 | '4': 2419 | 'name': 'comment.line.keyword.punctuation.yard.ruby' 2420 | '5': 2421 | 'name': 'comment.line.keyword.yard.ruby' 2422 | 'name': 'comment.line.number-sign.ruby' 2423 | 'yard_types': 2424 | 'comment': 'For YARD tags that follow the tag-types-comment pattern' 2425 | 'begin': '^(\\s*)(#)(\\s*)(@)(raise|return|yield(?:return)?)(?=\\s)(\\s+((\\[).+(])))?' 2426 | 'beginCaptures': 2427 | '1': 2428 | 'name': '' 2429 | '2': 2430 | 'name': 'punctuation.definition.comment.ruby' 2431 | '3': 2432 | 'name': '' 2433 | '4': 2434 | 'name': 'comment.line.keyword.punctuation.yard.ruby' 2435 | '5': 2436 | 'name': 'comment.line.keyword.yard.ruby' 2437 | '6': 2438 | 'name': 'comment.line.yard.ruby' 2439 | '7': 2440 | 'name': 'comment.line.type.yard.ruby' 2441 | '8': 2442 | 'name': 'comment.line.punctuation.yard.ruby' 2443 | '9': 2444 | 'name': 'comment.line.punctuation.yard.ruby' 2445 | 'end': '^(?!\\s*#\\3\\s{2,})' 2446 | 'contentName': 'comment.line.string.yard.ruby' 2447 | 'name': 'comment.line.number-sign.ruby' 2448 | 'patterns': [ 2449 | { 2450 | 'include': '#yard' 2451 | } 2452 | { 2453 | 'include': '#yard_continuation' 2454 | } 2455 | ] 2456 | 'yard_directive': 2457 | 'comment': 'For YARD directives' 2458 | 'begin': '^(\\s*)(#)(\\s*)(@!)(attribute|endgroup|group|macro|method|parse|scope|visibility)(\\s+((\\[).+(])))?(?=\\s)' 2459 | 'beginCaptures': 2460 | '1': 2461 | 'name': '' 2462 | '2': 2463 | 'name': 'punctuation.definition.comment.ruby' 2464 | '3': 2465 | 'name': '' 2466 | '4': 2467 | 'name': 'comment.line.keyword.punctuation.yard.ruby' 2468 | '5': 2469 | 'name': 'comment.line.keyword.yard.ruby' 2470 | '6': 2471 | 'name': 'comment.line.yard.ruby' 2472 | '7': 2473 | 'name': 'comment.line.type.yard.ruby' 2474 | '8': 2475 | 'name': 'comment.line.punctuation.yard.ruby' 2476 | '9': 2477 | 'name': 'comment.line.punctuation.yard.ruby' 2478 | 'end': '^(?!\\s*#\\3\\s{2,})' 2479 | 'contentName': 'comment.line.string.yard.ruby' 2480 | 'name': 'comment.line.number-sign.ruby' 2481 | 'patterns': [ 2482 | { 2483 | 'include': '#yard' 2484 | } 2485 | { 2486 | 'include': '#yard_continuation' 2487 | } 2488 | ] 2489 | 'yard_continuation': 2490 | 'match': '^\\s*#' 2491 | 'name': 'punctuation.definition.comment.ruby' 2492 | -------------------------------------------------------------------------------- /grammars/tree-sitter-ruby.cson: -------------------------------------------------------------------------------- 1 | name: 'Ruby' 2 | scopeName: 'source.ruby' 3 | type: 'tree-sitter' 4 | parser: 'tree-sitter-ruby' 5 | 6 | injectionRegex: 'rb|ruby' 7 | 8 | firstLineRegex: [ 9 | # shebang line 10 | '^#!.*\\b(\w*ruby|rake)\\r?\\n' 11 | 12 | # vim modeline 13 | 'vim\\b.*\\bset\\b.*\\b(filetype|ft|syntax)=ruby' 14 | ] 15 | 16 | fileTypes: [ 17 | 'rb', 18 | 'rake', 19 | 'Podfile', 20 | 'Brewfile', 21 | 'Rakefile', 22 | 'Gemfile' 23 | ] 24 | 25 | comments: 26 | start: '# ' 27 | 28 | folds: [ 29 | { 30 | type: ['block', 'do_block'] 31 | start: {type: 'block_parameters'} 32 | end: {index: -1} 33 | } 34 | { 35 | type: 'begin' 36 | start: {index: 0} 37 | end: {type: 'rescue'} 38 | } 39 | { 40 | type: 'heredoc_body', 41 | end: {type: 'heredoc_end'} 42 | } 43 | { 44 | type: [ 45 | 'hash' 46 | 'array' 47 | 'begin' 48 | 'block' 49 | 'do_block' 50 | ] 51 | start: {index: 0} 52 | end: {index: -1} 53 | } 54 | { 55 | type: 'argument_list' 56 | start: {index: 0, type: '('} 57 | end: {index: -1} 58 | } 59 | { 60 | type: 'class' 61 | start: {type: 'superclass'} 62 | end: {index: -1} 63 | } 64 | { 65 | type: 'class' 66 | start: {index: 1} 67 | end: {index: -1} 68 | } 69 | { 70 | type: ['method', 'singleton_method'] 71 | start: {type: 'method_parameters'} 72 | end: {index: -1} 73 | } 74 | { 75 | type: ['method', 'singleton_method'] 76 | start: {index: 1} 77 | end: {index: -1} 78 | } 79 | { 80 | type: 'then', 81 | start: {index: 0, type: '"then"'} 82 | } 83 | { 84 | type: 'then' 85 | } 86 | { 87 | type: 'case', 88 | end: {index: -1} 89 | } 90 | { 91 | type: 'else' 92 | start: {index: 0} 93 | } 94 | ] 95 | 96 | scopes: 97 | 'program': 'source.ruby' 98 | 99 | '"if"': 'keyword.control' 100 | '"unless"': 'keyword.control' 101 | '"def"': 'keyword.control' 102 | '"do"': 'keyword.control' 103 | '"end"': 'keyword.control' 104 | '"else"': 'keyword.control' 105 | '"elsif"': 'keyword.control' 106 | '"class"': 'keyword.control' 107 | '"module"': 'keyword.control' 108 | '"begin"': 'keyword.control' 109 | '"rescue"': 'keyword.control' 110 | '"ensure"': 'keyword.control' 111 | '"return"': 'keyword.control' 112 | '"yield"': 'keyword.control' 113 | '"case"': 'keyword.control' 114 | '"when"': 'keyword.control' 115 | '"then"': 'keyword.control' 116 | '"for"': 'keyword.control' 117 | '"break"': 'keyword.control' 118 | '"next"': 'keyword.control' 119 | '"retry"': 'keyword.control' 120 | '"while"': 'keyword.control' 121 | '"in"': 'keyword.control' 122 | '"until"': 'keyword.control' 123 | '"defined?"': 'keyword.control' 124 | '"alias"': 'keyword.control' 125 | '"undef"': 'keyword.control' 126 | 'super': 'keyword.control' 127 | 128 | 'interpolation': 'embedded.source' 129 | 'interpolation > "#{"': 'punctuation.section.embedded' 130 | 'interpolation > "}"': 'punctuation.section.embedded' 131 | 132 | 'constant': [ 133 | {match: '^[A-Z_0-9]+$', scopes: 'variable.constant'} 134 | 'entity.name.type.class' 135 | ] 136 | 'global_variable': 'variable.other.readwrite.global' 137 | 'superclass > constant': 'entity.other.inherited-class' 138 | 139 | 'identifier': [ 140 | { 141 | match: '^__(FILE|LINE|ENCODING)__$', 142 | scopes: 'support.variable' 143 | } 144 | { 145 | match: '^(public|protected|private)$' 146 | scopes: 'keyword.other.special-method' 147 | } 148 | { 149 | match: '^(block_given\?|iterator\?|alias_method)' 150 | scopes: 'keyword.control' 151 | } 152 | ] 153 | 154 | 'escape_sequence': 'constant.character.escape' 155 | 156 | 'self': 'variable.language' 157 | 158 | '"%w("': 'punctuation.definition.parameters' 159 | '"%i("': 'punctuation.definition.parameters' 160 | '"("': 'punctuation.definition.parameters' 161 | '")"': 'punctuation.definition.parameters' 162 | 163 | 'method > identifier': 'entity.name.function' 164 | 'assignment > identifier': 'variable' 165 | 166 | 'singleton_method > identifier:nth-child(3)': 'entity.name.function' 167 | 'setter > identifier': 'entity.name.function' 168 | 'call > identifier:nth-child(2)': 'entity.name.function' 169 | 'method_call > identifier:nth-child(0)': [ 170 | {exact: 'require', scopes: 'support.function'} 171 | {match: '^(public|protected|private)$', scopes: 'keyword.other.special-method'} 172 | {match: '^(block_given\?|iterator\?|alias_method)', scopes: 'keyword.control'} 173 | 'entity.name.function' 174 | ] 175 | 176 | 'block_parameters > identifier': 'variable.other.block' 177 | 'method_parameters > identifier, optional_parameter > identifier': 'variable.parameter.function' 178 | 'keyword_parameter > identifier:nth-child(0)': 'constant.other.symbol' 179 | 'class_variable': 'variable.other.object.property' 180 | 'instance_variable': 'variable.other.object.property' 181 | 'symbol': 'constant.other.symbol' 182 | 'bare_symbol': 'constant.other.symbol' 183 | 184 | 'comment': 'comment' 185 | 'regex': 'string.regexp' 186 | 'float': 'constant.numeric' 187 | 'integer': 'constant.numeric' 188 | 189 | 'string': [ 190 | {match: '^"', scopes: 'string.quoted.double.interpolated'} 191 | {match: "^'", scopes: 'string.quoted.single'} 192 | 'string' 193 | ] 194 | 195 | # Quote delimiters are the only two children of these kinds of strings. If 196 | # this changes in the tree-sitter parser in the future, these selectors will 197 | # need updating. 198 | "string > '\"':nth-child(0)": 'punctuation.definition.string.begin' 199 | "string > '\"':nth-child(1)": 'punctuation.definition.string.end' 200 | 'string > "\'":nth-child(0)': 'punctuation.definition.string.begin' 201 | 'string > "\'":nth-child(1)': 'punctuation.definition.string.end' 202 | 203 | 'heredoc_beginning, heredoc_body': 'string.unquoted.heredoc.interpolated' 204 | 'subshell': 'string.quoted.subshell.interpolated' 205 | 'bare_string': 'string.unquoted.other' 206 | 207 | '"="': 'keyword.operator.assignment' 208 | 209 | '"+="': 'keyword.operator.assignment.augmented' 210 | '"-="': 'keyword.operator.assignment.augmented' 211 | '"*="': 'keyword.operator.assignment.augmented' 212 | '"/="': 'keyword.operator.assignment.augmented' 213 | '"<<="': 'keyword.operator.assignment.augmented' 214 | '"%="': 'keyword.operator.assignment.augmented' 215 | '"&="': 'keyword.operator.assignment.augmented' 216 | '"&&="': 'keyword.operator.assignment.augmented' 217 | '"|="': 'keyword.operator.assignment.augmented' 218 | '"||="': 'keyword.operator.assignment.augmented' 219 | '"**="': 'keyword.operator.assignment.augmented' 220 | '"^="': 'keyword.operator.assignment.augmented' 221 | 222 | '"<=>"': 'keyword.operator.comparison' 223 | '"<"': 'keyword.operator.comparison' 224 | '">"': 'keyword.operator.comparison' 225 | '"<="': 'keyword.operator.comparison' 226 | '">="': 'keyword.operator.comparison' 227 | '"==="': 'keyword.operator.comparison' 228 | '"=="': 'keyword.operator.comparison' 229 | '"=~"': 'keyword.operator.comparison' 230 | '"!="': 'keyword.operator.comparison' 231 | '"!~"': 'keyword.operator.comparison' 232 | 233 | '"&&"': 'keyword.operator.logical' 234 | '"!"': 'keyword.operator.logical' 235 | '"||"': 'keyword.operator.logical' 236 | '"and"': 'keyword.operator.logical' 237 | '"not"': 'keyword.operator.logical' 238 | '"or"': 'keyword.operator.logical' 239 | '"^"': 'keyword.operator.logical' 240 | 241 | '"+"': 'keyword.operator.arithmetic' 242 | '"-"': 'keyword.operator.arithmetic' 243 | '"*"': 'keyword.operator.arithmetic' 244 | '"/"': 'keyword.operator.arithmetic' 245 | '"**"': 'keyword.operator.arithmetic' 246 | '"&"': 'keyword.operator.arithmetic' 247 | '"%"': 'keyword.operator.arithmetic' 248 | 249 | 'call > ".", call > "&."': 'punctuation.separator.method' 250 | 251 | '";"': 'punctuation.separator.statement' 252 | '","': 'punctuation.separator.object' 253 | 254 | 'nil': 'constant.language.nil' 255 | 'true': 'constant.language.true' 256 | 'false': 'constant.language.false' 257 | -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | exports.activate = function() { 2 | if (!atom.grammars.addInjectionPoint) return 3 | 4 | atom.grammars.addInjectionPoint('source.ruby', { 5 | type: 'heredoc_body', 6 | language (node) { return node.lastChild.text }, 7 | content (node) { return node } 8 | }) 9 | 10 | atom.grammars.addInjectionPoint('source.ruby', { 11 | type: 'regex', 12 | language () { return 'regex' }, 13 | content (node) { return node } 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "language-ruby", 3 | "version": "0.73.0", 4 | "description": "Ruby language support in Atom", 5 | "keywords": [ 6 | "tree-sitter" 7 | ], 8 | "engines": { 9 | "atom": "*", 10 | "node": "*" 11 | }, 12 | "main": "lib/main", 13 | "license": "MIT", 14 | "repository": "https://github.com/atom/language-ruby", 15 | "dependencies": { 16 | "tree-sitter-ruby": "^0.17.0" 17 | }, 18 | "devDependencies": { 19 | "coffeelint": "^1.10.1", 20 | "dedent": "^0.7.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /settings/language-ruby.cson: -------------------------------------------------------------------------------- 1 | '.source.ruby': 2 | 'editor': 3 | 'commentStart': '# ' 4 | 'increaseIndentPattern': '(?x)^\n (\\s*\n (module|class|(private\\s+)?def\n |unless|if|else|elsif\n |case|when\n |begin|rescue|ensure\n |for|while|until\n |(?= .*? \\b(do|begin|case|if|unless)\\b )\n # the look-ahead above is to quickly discard non-candidates\n ( "(\\\\.|[^\\\\"])*+" # eat a double quoted string\n | \'(\\\\.|[^\\\\\'])*+\' # eat a single quoted string\n | [^#"\'] # eat all but comments and strings\n )*\n ( \\s (do|begin|case)\n | [-+=&|*/~%^<>~](?\n\t\t|^\\s*-->\n\t\t|(^|\\s)\\}\n\t\t)' 9 | '.source.ruby:not(.string.unquoted.heredoc)': 10 | 'editor': 11 | 'foldEndPattern': '(?x)\n\t\t( (^|;) \\s*+ end \\s*+ ([#].*)? $\n\t\t| (^|;) \\s*+ end \\. .* $\n\t\t| ^ \\s*+ [}\\]] ,? \\s*+ ([#].*)? $\n\t\t| [#] .*? \\(end\\) \\s*+ $ # Sune’s special marker\n\t\t| ^=end\n\t\t)\n\t' 12 | -------------------------------------------------------------------------------- /snippets/language-ruby.cson: -------------------------------------------------------------------------------- 1 | '.source.ruby, .dyn.caret.begin.document': 2 | '#!/usr/bin/env ruby -wKU': 3 | 'prefix': 'rb' 4 | 'body': '#!/usr/bin/env ruby -wKU\n' 5 | '.source.ruby': 6 | '# encoding: UTF-8': 7 | 'prefix': 'utf8' 8 | 'body': '# encoding: ${1:UTF-8}\n' 9 | 'if … else … end': 10 | 'prefix': 'ife' 11 | 'body': 'if ${1:condition}\n\t$2\nelse\n\t$3\nend' 12 | 'if … end': 13 | 'prefix': 'if' 14 | 'body': 'if ${1:condition}\n\t$0\nend' 15 | 'it … end': 16 | 'prefix': 'it' 17 | 'body': 'it "${1:text}" do\n\t$0\nend' 18 | 'case … end': 19 | 'prefix': 'case' 20 | 'body': 'case ${1:object}\nwhen ${2:condition}\n\t$0\nend' 21 | 'begin … rescue … end': 22 | 'prefix': 'beg' 23 | 'body': 'begin\n\t$1\nrescue ${2:ExceptionName}\n\t$3\nend' 24 | 'refine … end': 25 | 'prefix': 'ref' 26 | 'body': 'refine ${1:ClassName} do\n\t$2\nend' 27 | 'using': 28 | 'prefix': 'usi' 29 | 'body': 'using ${1:ModuleName}' 30 | 'Add ‘# =>’ Marker': 31 | 'prefix': '#' 32 | 'body': '# => ' 33 | 'Benchmark.bmbm do .. end': 34 | 'prefix': 'bm-' 35 | 'body': 'TESTS = ${1:10_000}\nBenchmark.bmbm do |results|\n $0\nend' 36 | 'Dir.glob("..") { |file| .. }': 37 | 'prefix': 'Dirg' 38 | 'body': 'Dir.glob(${1:"${2:dir/glob/*}"}) { |${3:file}| $0 }' 39 | 'Dir[".."]': 40 | 'prefix': 'Dir' 41 | 'body': 'Dir[${1:"${2:glob/**/*.rb}"}]' 42 | 'File.foreach ("..") { |line| .. }': 43 | 'prefix': 'Filef' 44 | 'body': 'File.foreach(${1:"${2:path/to/file}"}) { |${3:line}| $0 }' 45 | 'File.read("..")': 46 | 'prefix': 'File' 47 | 'body': 'File.read(${1:"${2:path/to/file}"})' 48 | 'Hash.new { |hash, key| hash[key] = .. }': 49 | 'prefix': 'Hash' 50 | 'body': 'Hash.new { |${1:hash}, ${2:key}| ${1:hash}[${2:key}] = $0 }' 51 | 'Array.new( .. )': 52 | 'prefix': 'arr' 53 | 'body': 'Array.new(${1:len,val})\n$0' 54 | 'Array.new( .. ) { |index| .. }': 55 | 'prefix': 'arri' 56 | 'body': 'Array.new(${1:len}) { |${2:i}| $0 }' 57 | 'Marshal.dump(.., file)': 58 | 'prefix': 'Md' 59 | 'body': 'File.open(${1:"${2:path/to/file}.dump"}, "wb") { |${3:file}| Marshal.dump(${4:obj}, ${3:file}) }' 60 | 'Marshal.load(obj)': 61 | 'prefix': 'Ml' 62 | 'body': 'File.open(${1:"${2:path/to/file}.dump"}, "rb") { |${3:file}| Marshal.load(${3:file}) }' 63 | 'PStore.new( .. )': 64 | 'prefix': 'Pn-' 65 | 'body': 'PStore.new(${1:"${2:file_name.pstore}"})' 66 | 'YAML.dump(.., file)': 67 | 'prefix': 'Yd-' 68 | 'body': 'File.open(${1:"${2:path/to/file}.yaml"}, "w") { |${3:file}| YAML.dump(${4:obj}, ${3:file}) }' 69 | 'YAML.load(file)': 70 | 'prefix': 'Yl-' 71 | 'body': 'File.open(${1:"${2:path/to/file}.yaml"}) { |${3:file}| YAML.load(${3:file}) }' 72 | 'alias_method ..': 73 | 'prefix': 'am' 74 | 'body': 'alias_method :${1:new_name}, :${0:old_name}' 75 | 'all? { |e| .. }': 76 | 'prefix': 'all' 77 | 'body': 'all? { |${1:e}| $0 }' 78 | 'any? { |e| .. }': 79 | 'prefix': 'any' 80 | 'body': 'any? { |${1:e}| $0 }' 81 | 'application { .. }': 82 | 'prefix': 'app' 83 | 'body': 'if __FILE__ == \\$PROGRAM_NAME\n\t$0\nend' 84 | 'assert_nothing_raised(..) { .. }': 85 | 'prefix': 'asnr' 86 | 'body': 'assert_nothing_raised(${1:Exception}) { $0 }' 87 | 'assert_nothing_thrown { .. }': 88 | 'prefix': 'asnt' 89 | 'body': 'assert_nothing_thrown { $0 }' 90 | 'assert_raise(..) { .. }': 91 | 'prefix': 'asr' 92 | 'body': 'assert_raise(${1:Exception}) { $0 }' 93 | 'assert_throws(..) { .. }': 94 | 'prefix': 'ast' 95 | 'body': 'assert_throws(:${1:expected}) { $0 }' 96 | 'attr_accessor ..': 97 | 'prefix': 'rw' 98 | 'body': 'attr_accessor :${0:attr_names}' 99 | 'attr_reader ..': 100 | 'prefix': 'r' 101 | 'body': 'attr_reader :${0:attr_names}' 102 | 'attr_writer ..': 103 | 'prefix': 'w' 104 | 'body': 'attr_writer :${0:attr_names}' 105 | 'ClassName = Struct .. do .. end': 106 | 'prefix': 'clast' 107 | 'body': '$1 = Struct.new(:${2:attr_names}) do\n\tdef ${3:method_name}\n\t\t$0\n\tend\n\t\n\t\nend' 108 | 'class << self .. end': 109 | 'prefix': 'clase' 110 | 'body': 'class << ${1:self}\n\t$0\nend' 111 | 'class .. end': 112 | 'prefix': 'cla' 113 | 'body': 'class ${1:ClassName}\n\t$0\nend' 114 | 'class_from_name()': 115 | 'prefix': 'clafn' 116 | 'body': 'split("::").inject(Object) { |par, const| par.const_get(const) }' 117 | 'collect { |e| .. }': 118 | 'prefix': 'col' 119 | 'body': 'collect { |${1:e}| $0 }' 120 | 'deep_copy(..)': 121 | 'prefix': 'deec' 122 | 'body': 'Marshal.load(Marshal.dump(${0:obj_to_copy}))' 123 | 'def … end': 124 | 'prefix': 'def' 125 | 'body': 'def ${1:method_name}\n\t$0\nend' 126 | 'initialize': 127 | 'prefix': 'defi' 128 | 'body': 'def initialize${1:(${2:argument})}\n\t\@${2:argument} = ${2:argument}$0\nend' 129 | 'def method_missing .. end': 130 | 'prefix': 'defmm' 131 | 'body': 'def method_missing(meth, *args, &blk)\n\t$0\nend' 132 | 'def self .. end': 133 | 'prefix': 'defs' 134 | 'body': 'def self.${1:class_method_name}\n\t$0\nend' 135 | 'def test_ .. end': 136 | 'prefix': 'deft' 137 | 'body': 'def test_${1:case_name}\n\t$0\nend' 138 | 'def_delegator ..': 139 | 'prefix': 'defd' 140 | 'body': 'def_delegator :${1:@del_obj}, :${2:del_meth}, :${3:new_name}' 141 | 'def_delegators ..': 142 | 'prefix': 'defds' 143 | 'body': 'def_delegators :${1:@del_obj}, :${0:del_methods}' 144 | 'delete_if { |e| .. }': 145 | 'prefix': 'deli' 146 | 'body': 'delete_if { |${1:e}| $0 }' 147 | 'detect { |e| .. }': 148 | 'prefix': 'det' 149 | 'body': 'detect { |${1:e}| $0 }' 150 | 'directory()': 151 | 'prefix': 'dir' 152 | 'body': 'File.dirname(__FILE__)' 153 | 'Insert do … end': 154 | 'prefix': 'do' 155 | 'body': 'do\n\t$0\nend' 156 | 'Insert do |variable| … end': 157 | 'prefix': 'dop' 158 | 'body': 'do |${1:variable}|\n\t$0\nend' 159 | 'each { |e| .. }': 160 | 'prefix': 'ea' 161 | 'body': 'each { |${1:e}| $0 }' 162 | 'each_byte { |byte| .. }': 163 | 'prefix': 'eab' 164 | 'body': 'each_byte { |${1:byte}| $0 }' 165 | 'each_char { |chr| .. }': 166 | 'prefix': 'eacha' 167 | 'body': 'each_char { |${1:chr}| $0 }' 168 | 'each_cons(..) { |group| .. }': 169 | 'prefix': 'eacon' 170 | 'body': 'each_cons(${1:2}) { |${2:group}| $0 }' 171 | 'each_index { |i| .. }': 172 | 'prefix': 'eai' 173 | 'body': 'each_index { |${1:i}| $0 }' 174 | 'each_key { |key| .. }': 175 | 'prefix': 'eak' 176 | 'body': 'each_key { |${1:key}| $0 }' 177 | 'each_line { |line| .. }': 178 | 'prefix': 'eal' 179 | 'body': 'each_line$1 { |${2:line}| $0 }' 180 | 'each_pair { |name, val| .. }': 181 | 'prefix': 'eap' 182 | 'body': 'each_pair { |${1:name}, ${2:val}| $0 }' 183 | 'each_slice(..) { |group| .. }': 184 | 'prefix': 'eas-' 185 | 'body': 'each_slice(${1:2}) { |${2:group}| $0 }' 186 | 'each_value { |val| .. }': 187 | 'prefix': 'eav' 188 | 'body': 'each_value { |${1:val}| $0 }' 189 | 'each_with_index { |e, i| .. }': 190 | 'prefix': 'eawi' 191 | 'body': 'each_with_index { |${1:e}, ${2:i}| $0 }' 192 | 'elsif ...': 193 | 'prefix': 'elsif' 194 | 'body': 'elsif ${1:condition}\n\t$0' 195 | 'extend Forwardable': 196 | 'prefix': 'Forw' 197 | 'body': 'extend Forwardable' 198 | 'find { |e| .. }': 199 | 'prefix': 'fin' 200 | 'body': 'find { |${1:e}| $0 }' 201 | 'find_all { |e| .. }': 202 | 'prefix': 'fina' 203 | 'body': 'find_all { |${1:e}| $0 }' 204 | 'flatten_once()': 205 | 'prefix': 'flao' 206 | 'body': 'inject(Array.new) { |${1:arr}, ${2:a}| ${1:arr}.push(*${2:a}) }' 207 | 'grep(/pattern/) { |match| .. }': 208 | 'prefix': 'gre' 209 | 'body': 'grep(${1:/${2:pattern}/}) { |${3:match}| $0 }' 210 | 'Hash Pair — :key => "value"': 211 | 'prefix': 'hp' 212 | 'body': ':${1:key} => ${2:"${3:value}"}${4:, }' 213 | 'include Comparable ..': 214 | 'prefix': 'Comp' 215 | 'body': 'include Comparable\n\ndef <=>(other)\n\t$0\nend' 216 | 'include Enumerable ..': 217 | 'prefix': 'Enum' 218 | 'body': 'include Enumerable\n\ndef each(&block)\n\t$0\nend' 219 | 'loop { .. }': 220 | 'prefix': 'loo' 221 | 'body': 'loop { $0 }' 222 | 'map { |e| .. }': 223 | 'prefix': 'map' 224 | 'body': 'map { |${1:e}| $0 }' 225 | 'map_with_index { |e, i| .. }': 226 | 'prefix': 'mapwi-' 227 | 'body': 'enum_with_index.map { |${1:e}, ${2:i}| $0 }' 228 | 'max { |a, b| .. }': 229 | 'prefix': 'max' 230 | 'body': 'max { |a, b| $0 }' 231 | 'min { |a, b| .. }': 232 | 'prefix': 'min' 233 | 'body': 'min { |a, b| $0 }' 234 | 'module .. module_function .. end': 235 | 'prefix': 'modf' 236 | 'body': 'module $1\n\tmodule_function\n\t\n\t$0\nend' 237 | 'module .. end': 238 | 'prefix': 'mod' 239 | 'body': 'module ${1:ModuleName}\n\t$0\nend' 240 | 'namespace :.. do .. end': 241 | 'prefix': 'nam' 242 | 'body': 'namespace :$1 do\n\t$0\nend' 243 | 'partition { |e| .. }': 244 | 'prefix': 'par' 245 | 'body': 'partition { |${1:e}| $0 }' 246 | 'path_from_here( .. )': 247 | 'prefix': 'patfh' 248 | 'body': 'File.join(File.dirname(__FILE__), *%w[${1:rel path here}])' 249 | 'randomize()': 250 | 'prefix': 'ran' 251 | 'body': 'sort_by { rand }' 252 | 'reject { |e| .. }': 253 | 'prefix': 'rej' 254 | 'body': 'reject { |${1:e}| $0 }' 255 | 'require ".."': 256 | 'prefix': 'req' 257 | 'body': 'require "$0"' 258 | 'require "tc_.." ..': 259 | 'prefix': 'ts' 260 | 'body': 'require "test/unit"\n\nrequire "tc_${1:test_case_file}"\nrequire "tc_${2:test_case_file}"\n' 261 | 'require_gem ".."': 262 | 'prefix': 'reqg-' 263 | 'body': 'require "$0"' 264 | 'results.report(..) { .. }': 265 | 'prefix': 'rep' 266 | 'body': 'results.report("${1:name}:") { TESTS.times { $0 } }' 267 | 'reverse_each { |e| .. }': 268 | 'prefix': 'reve' 269 | 'body': 'reverse_each { |${1:e}| $0 }' 270 | 'scan(/../) { |match| .. }': 271 | 'prefix': 'sca' 272 | 'body': 'scan(/${1:pattern}/) { |${2:match}| $0 }' 273 | 'select { |e| .. }': 274 | 'prefix': 'sel' 275 | 'body': 'select { |${1:e}| $0 }' 276 | 'singleton_class()': 277 | 'prefix': 'sinc' 278 | 'body': 'class << self; self end' 279 | 'sort { |a, b| .. }': 280 | 'prefix': 'sor' 281 | 'body': 'sort { |a, b| $0 }' 282 | 'sort_by { |e| .. }': 283 | 'prefix': 'sorb' 284 | 'body': 'sort_by { |${1:e}| $0 }' 285 | 'task :task_name => [:dependent, :tasks] do .. end': 286 | 'prefix': 'tas' 287 | 'body': 'desc "${1:Task description}"\ntask :${2:${3:task_name} => ${4:[:${5:dependent, :tasks}]}} do\n\t$0\nend' 288 | 'unix_filter { .. }': 289 | 'prefix': 'unif' 290 | 'body': 'ARGF.each_line$1 do |${2:line}|\n\t$0\nend' 291 | 'unless … end': 292 | 'prefix': 'unless' 293 | 'body': 'unless ${1:condition}\n\t$0\nend' 294 | 'until ... end': 295 | 'prefix': 'until' 296 | 'body': 'until ${1:condition}\n\t$0\nend' 297 | 'usage_if()': 298 | 'prefix': 'usai' 299 | 'body': 'if ARGV.$1\n\tabort "Usage: #\{\\$PROGRAM_NAME} ${2:ARGS_GO_HERE}"\nend' # '"#{var}"' makes a coffeelint issue. Use '"#\{var}"' instead. 300 | 'usage_unless()': 301 | 'prefix': 'usau' 302 | 'body': 'unless ARGV.$1\n\tabort "Usage: #\{\\$PROGRAM_NAME} ${2:ARGS_GO_HERE}"\nend' # '"#{var}"' makes a coffeelint issue. Use '"#\{var}"' instead. 303 | 'when …': 304 | 'prefix': 'when' 305 | 'body': 'when ${1:condition}\n\t$0' 306 | 'while ... end': 307 | 'prefix': 'while' 308 | 'body': 'while ${1:condition}\n\t$0\nend' 309 | 'xmlread(..)': 310 | 'prefix': 'xml-' 311 | 'body': 'REXML::Document.new(File.read(${1:"${2:path/to/file}"}))' 312 | 'xpath(..) { .. }': 313 | 'prefix': 'xpa' 314 | 'body': 'elements.each(${1:"${2://XPath}"}) do |${3:node}|\n\t$0\nend' 315 | 'zip(enums) { |row| .. }': 316 | 'prefix': 'zip' 317 | 'body': 'zip(${1:enums}) { |${2:row}| $0 }' 318 | 'pry': 319 | 'prefix': 'pry' 320 | 'body': 'binding.pry' 321 | 'Insert curly braces block': 322 | 'prefix': '{' 323 | 'body': '{ ${1:|${2:variable}| }$0 ' 324 | '.source.ruby .comment': 325 | ':yields:': 326 | 'prefix': 'y' 327 | 'body': ' :yields: ${0:arguments}' 328 | '.text.html.erb': 329 | 'erb_render_block': 330 | 'prefix': '=' 331 | 'body': '<%= $1 %>' 332 | 'erb_render_block_after_tag': 333 | 'prefix': '\>=' 334 | 'body': '\><%= $1 %>' 335 | 'erb_render_block_after_quote': 336 | 'prefix': '\"=' 337 | 'body': '\"<%= $1 %>' 338 | 'erb_exec_block': 339 | 'prefix': '-' 340 | 'body': '<% $1 %>' 341 | 'erb_exec_block_after_tag': 342 | 'prefix': '\>-' 343 | 'body': '\><% $1 %>' 344 | 'erb_exec_block_after_quote': 345 | 'prefix': '\"-' 346 | 'body': '\"<% $1 %>' 347 | 348 | '.string.quoted.double.ruby:not(.string .source), .string.quoted.double.ruby:not(.string .source)': 349 | 'Interpolated Code': 350 | 'prefix': '#' 351 | 'body': '#{$1}$2' 352 | -------------------------------------------------------------------------------- /spec/erb-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "TextMate HTML (Ruby - ERB) grammar", -> 2 | grammar = null 3 | 4 | beforeEach -> 5 | atom.config.set('core.useTreeSitterParsers', false) 6 | 7 | waitsForPromise -> 8 | atom.packages.activatePackage("language-ruby") 9 | 10 | runs -> 11 | grammar = atom.grammars.grammarForScopeName("text.html.erb") 12 | 13 | it "parses the grammar", -> 14 | expect(grammar).toBeTruthy() 15 | expect(grammar.scopeName).toBe "text.html.erb" 16 | 17 | it "tokenizes embedded ruby", -> 18 | {tokens} = grammar.tokenizeLine('<%= self %>') 19 | expect(tokens[0]).toEqual value: '<%=', scopes: ['text.html.erb', 'meta.embedded.line.erb', 'punctuation.section.embedded.begin.erb'] 20 | expect(tokens[1]).toEqual value: ' ', scopes: ['text.html.erb', 'meta.embedded.line.erb', 'source.ruby.embedded.erb'] 21 | expect(tokens[2]).toEqual value: 'self', scopes: ['text.html.erb', 'meta.embedded.line.erb', 'source.ruby.embedded.erb', 'variable.language.self.ruby'] 22 | expect(tokens[3]).toEqual value: ' ', scopes: ['text.html.erb', 'meta.embedded.line.erb', 'source.ruby.embedded.erb'] 23 | expect(tokens[4]).toEqual value: '%>', scopes: ['text.html.erb', 'meta.embedded.line.erb', 'punctuation.section.embedded.end.erb'] 24 | 25 | lines = grammar.tokenizeLines('<%=\nself\n%>') 26 | expect(lines[0][0]).toEqual value: '<%=', scopes: ['text.html.erb', 'meta.embedded.block.erb', 'punctuation.section.embedded.begin.erb'] 27 | expect(lines[1][0]).toEqual value: 'self', scopes: ['text.html.erb', 'meta.embedded.block.erb', 'source.ruby.embedded.erb', 'variable.language.self.ruby'] 28 | expect(lines[2][0]).toEqual value: '%>', scopes: ['text.html.erb', 'meta.embedded.block.erb', 'punctuation.section.embedded.end.erb'] 29 | -------------------------------------------------------------------------------- /spec/gemfile-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "TextMate Gemfile grammar", -> 2 | grammar = null 3 | 4 | beforeEach -> 5 | atom.config.set('core.useTreeSitterParsers', false) 6 | 7 | waitsForPromise -> 8 | atom.packages.activatePackage("language-ruby") 9 | 10 | runs -> 11 | grammar = atom.grammars.grammarForScopeName("source.ruby.gemfile") 12 | 13 | it "parses the grammar", -> 14 | expect(grammar).toBeTruthy() 15 | expect(grammar.scopeName).toBe "source.ruby.gemfile" 16 | 17 | it "tokenizes ruby", -> 18 | {tokens} = grammar.tokenizeLine('ruby') 19 | expect(tokens[0]).toEqual value: 'ruby', scopes: ['source.ruby.gemfile', 'meta.declaration.ruby.gemfile', 'keyword.other.special-method.ruby.gemfile'] 20 | 21 | it "tokenizes source", -> 22 | {tokens} = grammar.tokenizeLine('source') 23 | expect(tokens[0]).toEqual value: 'source', scopes: ['source.ruby.gemfile', 'meta.declaration.ruby.gemfile', 'keyword.other.special-method.ruby.gemfile'] 24 | 25 | it "tokenizes group", -> 26 | {tokens} = grammar.tokenizeLine('group') 27 | expect(tokens[0]).toEqual value: 'group', scopes: ['source.ruby.gemfile', 'meta.declaration.ruby.gemfile', 'keyword.other.special-method.ruby.gemfile'] 28 | 29 | it "tokenizes gem", -> 30 | {tokens} = grammar.tokenizeLine('gem') 31 | expect(tokens[0]).toEqual value: 'gem', scopes: ['source.ruby.gemfile', 'meta.declaration.ruby.gemfile', 'keyword.other.special-method.ruby.gemfile'] 32 | 33 | it "tokenizes double-quoted strings", -> 34 | {tokens} = grammar.tokenizeLine('"foo"') 35 | expect(tokens[0]).toEqual value: '"', scopes: ['source.ruby.gemfile', 'string.quoted.double.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 36 | expect(tokens[1]).toEqual value: 'foo', scopes: ['source.ruby.gemfile', 'string.quoted.double.interpolated.ruby'] 37 | expect(tokens[2]).toEqual value: '"', scopes: ['source.ruby.gemfile', 'string.quoted.double.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 38 | 39 | it "tokenizes single-quoted strings", -> 40 | {tokens} = grammar.tokenizeLine('\'foo\'') 41 | expect(tokens[0]).toEqual value: '\'', scopes: ['source.ruby.gemfile', 'string.quoted.single.ruby', 'punctuation.definition.string.begin.ruby'] 42 | expect(tokens[1]).toEqual value: 'foo', scopes: ['source.ruby.gemfile', 'string.quoted.single.ruby'] 43 | expect(tokens[2]).toEqual value: '\'', scopes: ['source.ruby.gemfile', 'string.quoted.single.ruby', 'punctuation.definition.string.end.ruby'] 44 | 45 | it "tokenizes group names", -> 46 | {tokens} = grammar.tokenizeLine(':foo') 47 | expect(tokens[0]).toEqual value: ':', scopes: ['source.ruby.gemfile', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby'] 48 | expect(tokens[1]).toEqual value: 'foo', scopes: ['source.ruby.gemfile', 'constant.other.symbol.ruby'] 49 | 50 | it "tokenizes group properly in ruby code", -> 51 | {tokens} = grammar.tokenizeLine('do |group|') 52 | expect(tokens[0]).toEqual value: 'do', scopes: ['source.ruby.gemfile', 'keyword.control.start-block.ruby'] 53 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby.gemfile'] 54 | expect(tokens[2]).toEqual value: '|', scopes: ['source.ruby.gemfile', 'punctuation.separator.variable.ruby'] 55 | expect(tokens[3]).toEqual value: 'group', scopes: ['source.ruby.gemfile', 'variable.other.block.ruby'] 56 | expect(tokens[4]).toEqual value: '|', scopes: ['source.ruby.gemfile', 'punctuation.separator.variable.ruby'] 57 | -------------------------------------------------------------------------------- /spec/ruby-spec.coffee: -------------------------------------------------------------------------------- 1 | describe "TextMate Ruby grammar", -> 2 | grammar = null 3 | 4 | beforeEach -> 5 | atom.config.set('core.useTreeSitterParsers', false) 6 | 7 | waitsForPromise -> 8 | atom.packages.activatePackage("language-ruby") 9 | 10 | runs -> 11 | grammar = atom.grammars.grammarForScopeName("source.ruby") 12 | 13 | it "parses the grammar", -> 14 | expect(grammar).toBeTruthy() 15 | expect(grammar.scopeName).toBe "source.ruby" 16 | 17 | it "tokenizes self", -> 18 | {tokens} = grammar.tokenizeLine('self') 19 | expect(tokens[0]).toEqual value: 'self', scopes: ['source.ruby', 'variable.language.self.ruby'] 20 | 21 | it "tokenizes special functions", -> 22 | {tokens} = grammar.tokenizeLine('require "."') 23 | expect(tokens[0]).toEqual value: 'require', scopes: ['source.ruby', 'meta.require.ruby', 'keyword.other.special-method.ruby'] 24 | 25 | {tokens} = grammar.tokenizeLine('Kernel.require "."') 26 | expect(tokens[1]).toEqual value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 27 | expect(tokens[2]).toEqual value: 'require ', scopes: ['source.ruby'] 28 | 29 | {tokens} = grammar.tokenizeLine('Kernel::require "."') 30 | expect(tokens[1]).toEqual value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 31 | expect(tokens[2]).toEqual value: 'require ', scopes: ['source.ruby'] 32 | 33 | {tokens} = grammar.tokenizeLine('thing&.call') 34 | expect(tokens[1]).toEqual value: '&.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 35 | expect(tokens[2]).toEqual value: 'call', scopes: ['source.ruby'] 36 | 37 | it "tokenizes variable constants", -> 38 | {tokens} = grammar.tokenizeLine('VAR1 = 100') 39 | expect(tokens[0]).toEqual value: 'VAR1', scopes: ['source.ruby', 'variable.other.constant.ruby'] 40 | 41 | {tokens} = grammar.tokenizeLine('_VAR2 = 200') 42 | expect(tokens[0]).toEqual value: '_VAR2', scopes: ['source.ruby', 'variable.other.constant.ruby'] 43 | 44 | it "tokenizes decimal numbers", -> 45 | {tokens} = grammar.tokenizeLine('100_000') 46 | expect(tokens[0]).toEqual value: '100_000', scopes: ['source.ruby', 'constant.numeric.ruby'] 47 | 48 | {tokens} = grammar.tokenizeLine('0') 49 | expect(tokens[0]).toEqual value: '0', scopes: ['source.ruby', 'constant.numeric.ruby'] 50 | 51 | {tokens} = grammar.tokenizeLine('1.23') 52 | expect(tokens[0]).toEqual value: '1.23', scopes: ['source.ruby', 'constant.numeric.ruby'] 53 | 54 | {tokens} = grammar.tokenizeLine('1.23e-4') 55 | expect(tokens[0]).toEqual value: '1.23e-4', scopes: ['source.ruby', 'constant.numeric.ruby'] 56 | 57 | {tokens} = grammar.tokenizeLine('0d100_000') 58 | expect(tokens[0]).toEqual value: '0d100_000', scopes: ['source.ruby', 'constant.numeric.ruby'] 59 | 60 | it "tokenizes hexadecimal numbers", -> 61 | {tokens} = grammar.tokenizeLine('0xAFFF') 62 | expect(tokens[0]).toEqual value: '0xAFFF', scopes: ['source.ruby', 'constant.numeric.ruby'] 63 | 64 | {tokens} = grammar.tokenizeLine('0XA_FFF') 65 | expect(tokens[0]).toEqual value: '0XA_FFF', scopes: ['source.ruby', 'constant.numeric.ruby'] 66 | 67 | it "tokenizes octal numbers", -> 68 | {tokens} = grammar.tokenizeLine('01_777') 69 | expect(tokens[0]).toEqual value: '01_777', scopes: ['source.ruby', 'constant.numeric.ruby'] 70 | 71 | {tokens} = grammar.tokenizeLine('0o1_777') 72 | expect(tokens[0]).toEqual value: '0o1_777', scopes: ['source.ruby', 'constant.numeric.ruby'] 73 | 74 | it "tokenizes binary numbers", -> 75 | {tokens} = grammar.tokenizeLine('0b100_000') 76 | expect(tokens[0]).toEqual value: '0b100_000', scopes: ['source.ruby', 'constant.numeric.ruby'] 77 | 78 | {tokens} = grammar.tokenizeLine('0B00100') 79 | expect(tokens[0]).toEqual value: '0B00100', scopes: ['source.ruby', 'constant.numeric.ruby'] 80 | 81 | it "tokenizes symbols", -> 82 | {tokens} = grammar.tokenizeLine(':test') 83 | expect(tokens[0]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby'] 84 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'constant.other.symbol.ruby'] 85 | 86 | {tokens} = grammar.tokenizeLine(':$symbol') 87 | expect(tokens[0]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby'] 88 | expect(tokens[1]).toEqual value: '$symbol', scopes: ['source.ruby', 'constant.other.symbol.ruby'] 89 | 90 | {tokens} = grammar.tokenizeLine(':<=>') 91 | expect(tokens[0]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.ruby', 'punctuation.definition.constant.ruby'] 92 | expect(tokens[1]).toEqual value: '<=>', scopes: ['source.ruby', 'constant.other.symbol.ruby'] 93 | 94 | it "tokenizes symbol as hash key (1.9 syntax)", -> 95 | {tokens} = grammar.tokenizeLine('foo: 1') 96 | expect(tokens[0]).toEqual value: 'foo', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby'] 97 | expect(tokens[1]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.hashkey.ruby'] 98 | expect(tokens[2]).toEqual value: ' ', scopes: ['source.ruby'] 99 | expect(tokens[3]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 100 | 101 | it "tokenizes symbol as hash key (1.8 syntax)", -> 102 | {tokens} = grammar.tokenizeLine(':foo => 1') 103 | expect(tokens[0]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.ruby'] 104 | expect(tokens[1]).toEqual value: 'foo', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby'] 105 | expect(tokens[2]).toEqual value: ' ', scopes: ['source.ruby'] 106 | expect(tokens[3]).toEqual value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby'] 107 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby'] 108 | expect(tokens[5]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 109 | 110 | it "tokenizes :: separators", -> 111 | {tokens} = grammar.tokenizeLine('File::read "test"') 112 | expect(tokens[0]).toEqual value: 'File', scopes: ['source.ruby', 'support.class.ruby'] 113 | expect(tokens[1]).toEqual value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 114 | expect(tokens[2]).toEqual value: 'read ', scopes: ['source.ruby'] 115 | 116 | {tokens} = grammar.tokenizeLine('File:: read "test"') 117 | expect(tokens[0]).toEqual value: 'File', scopes: ['source.ruby', 'variable.other.constant.ruby'] 118 | expect(tokens[1]).toEqual value: '::', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 119 | expect(tokens[2]).toEqual value: ' read ', scopes: ['source.ruby'] 120 | 121 | {tokens} = grammar.tokenizeLine('RbConfig::CONFIG') 122 | expect(tokens[0]).toEqual value: 'RbConfig', scopes: ['source.ruby', 'support.class.ruby'] 123 | expect(tokens[1]).toEqual value: '::', scopes: ['source.ruby', 'punctuation.separator.namespace.ruby'] 124 | expect(tokens[2]).toEqual value: 'CONFIG', scopes: ['source.ruby', 'variable.other.constant.ruby'] 125 | 126 | {tokens} = grammar.tokenizeLine('RbConfig:: CONFIG') 127 | expect(tokens[0]).toEqual value: 'RbConfig', scopes: ['source.ruby', 'variable.other.constant.ruby'] 128 | expect(tokens[1]).toEqual value: '::', scopes: ['source.ruby', 'punctuation.separator.namespace.ruby'] 129 | expect(tokens[2]).toEqual value: ' ', scopes: ['source.ruby'] 130 | expect(tokens[3]).toEqual value: 'CONFIG', scopes: ['source.ruby', 'variable.other.constant.ruby'] 131 | 132 | {tokens} = grammar.tokenizeLine('class A::B::C < ::D::E') 133 | expect(tokens[0]).toEqual value: 'class', scopes: ['source.ruby', 'meta.class.ruby', 'keyword.control.class.ruby'] 134 | expect(tokens[2]).toEqual value: 'A', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby'] 135 | expect(tokens[3]).toEqual value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.namespace.ruby'] 136 | expect(tokens[4]).toEqual value: 'B', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby'] 137 | expect(tokens[5]).toEqual value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.namespace.ruby'] 138 | expect(tokens[6]).toEqual value: 'C', scopes: ['source.ruby', 'meta.class.ruby', 'entity.name.type.class.ruby'] 139 | expect(tokens[8]).toEqual value: '<', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.separator.inheritance.ruby'] 140 | expect(tokens[10]).toEqual value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'punctuation.separator.namespace.ruby'] 141 | expect(tokens[11]).toEqual value: 'D', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'entity.name.type.class.ruby'] 142 | expect(tokens[12]).toEqual value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'punctuation.separator.namespace.ruby'] 143 | expect(tokens[13]).toEqual value: 'E', scopes: ['source.ruby', 'meta.class.ruby', 'entity.other.inherited-class.ruby', 'entity.name.type.class.ruby'] 144 | 145 | {tokens} = grammar.tokenizeLine('class << A::B') 146 | expect(tokens[0]).toEqual value: 'class', scopes: ['source.ruby', 'meta.class.ruby', 'keyword.control.class.ruby'] 147 | expect(tokens[2]).toEqual value: '<<', scopes: ['source.ruby', 'meta.class.ruby', 'punctuation.definition.variable.ruby'] 148 | expect(tokens[4]).toEqual value: 'A', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'entity.name.type.class.ruby'] 149 | expect(tokens[5]).toEqual value: '::', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'punctuation.separator.namespace.ruby'] 150 | expect(tokens[6]).toEqual value: 'B', scopes: ['source.ruby', 'meta.class.ruby', 'variable.other.object.ruby', 'entity.name.type.class.ruby'] 151 | 152 | {tokens} = grammar.tokenizeLine('module A::B::C') 153 | expect(tokens[0]).toEqual value: 'module', scopes: ['source.ruby', 'meta.module.ruby', 'keyword.control.module.ruby'] 154 | expect(tokens[2]).toEqual value: 'A', scopes: ['source.ruby', 'meta.module.ruby', 'entity.other.inherited-class.module.ruby'] 155 | expect(tokens[3]).toEqual value: '::', scopes: ['source.ruby', 'meta.module.ruby', 'punctuation.separator.namespace.ruby'] 156 | expect(tokens[4]).toEqual value: 'B', scopes: ['source.ruby', 'meta.module.ruby', 'entity.other.inherited-class.module.ruby'] 157 | expect(tokens[5]).toEqual value: '::', scopes: ['source.ruby', 'meta.module.ruby', 'punctuation.separator.namespace.ruby'] 158 | expect(tokens[6]).toEqual value: 'C', scopes: ['source.ruby', 'meta.module.ruby', 'entity.name.type.module.ruby'] 159 | 160 | it "tokenizes . separator", -> 161 | {tokens} = grammar.tokenizeLine('File.read "test"') 162 | expect(tokens[0]).toEqual value: 'File', scopes: ['source.ruby', 'support.class.ruby'] 163 | expect(tokens[1]).toEqual value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 164 | expect(tokens[2]).toEqual value: 'read ', scopes: ['source.ruby'] 165 | 166 | {tokens} = grammar.tokenizeLine('File. read "test"') 167 | expect(tokens[0]).toEqual value: 'File', scopes: ['source.ruby', 'variable.other.constant.ruby'] 168 | expect(tokens[1]).toEqual value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 169 | expect(tokens[2]).toEqual value: ' read ', scopes: ['source.ruby'] 170 | 171 | {tokens} = grammar.tokenizeLine('def a.b(*args)') 172 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 173 | expect(tokens[2]).toEqual value: 'a', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 174 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 175 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 176 | expect(tokens[5]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 177 | expect(tokens[6]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 178 | expect(tokens[7]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 179 | expect(tokens[8]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 180 | 181 | {tokens} = grammar.tokenizeLine('def a.b *args') 182 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 183 | expect(tokens[2]).toEqual value: 'a', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 184 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 185 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 186 | expect(tokens[6]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 187 | expect(tokens[7]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 188 | 189 | {tokens} = grammar.tokenizeLine('def a.b') 190 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'keyword.control.def.ruby'] 191 | expect(tokens[2]).toEqual value: 'a', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby'] 192 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 193 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby'] 194 | 195 | {tokens} = grammar.tokenizeLine('def self.b(*args)') 196 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 197 | expect(tokens[2]).toEqual value: 'self', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby'] 198 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 199 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 200 | expect(tokens[5]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 201 | expect(tokens[6]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 202 | expect(tokens[7]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 203 | expect(tokens[8]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 204 | 205 | {tokens} = grammar.tokenizeLine('def self.b *args') 206 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 207 | expect(tokens[2]).toEqual value: 'self', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby'] 208 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 209 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 210 | expect(tokens[6]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 211 | expect(tokens[7]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 212 | 213 | {tokens} = grammar.tokenizeLine('def self.b') 214 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'keyword.control.def.ruby'] 215 | expect(tokens[2]).toEqual value: 'self', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'variable.language.self.ruby'] 216 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby', 'punctuation.separator.method.ruby'] 217 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby', 'meta.function.method.without-arguments.ruby', 'entity.name.function.ruby'] 218 | 219 | it "tokenizes , separator", -> 220 | {tokens} = grammar.tokenizeLine('hash = {1 => \'one\', 2 => \'two\'}') 221 | expect(tokens[0]).toEqual value: 'hash ', scopes: ['source.ruby'] 222 | expect(tokens[1]).toEqual value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby'] 223 | expect(tokens[3]).toEqual value: '{', scopes: ['source.ruby', 'punctuation.section.scope.begin.ruby'] 224 | expect(tokens[4]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 225 | expect(tokens[6]).toEqual value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby'] 226 | expect(tokens[8]).toEqual value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.begin.ruby'] 227 | expect(tokens[9]).toEqual value: 'one', scopes: ['source.ruby', 'string.quoted.single.ruby'] 228 | expect(tokens[10]).toEqual value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.end.ruby'] 229 | expect(tokens[11]).toEqual value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby'] 230 | expect(tokens[13]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 231 | expect(tokens[15]).toEqual value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby'] 232 | expect(tokens[17]).toEqual value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.begin.ruby'] 233 | expect(tokens[18]).toEqual value: 'two', scopes: ['source.ruby', 'string.quoted.single.ruby'] 234 | expect(tokens[19]).toEqual value: '\'', scopes: ['source.ruby', 'string.quoted.single.ruby', 'punctuation.definition.string.end.ruby'] 235 | expect(tokens[20]).toEqual value: '}', scopes: ['source.ruby', 'punctuation.section.scope.end.ruby'] 236 | 237 | {tokens} = grammar.tokenizeLine('method(a,b)') 238 | expect(tokens[0]).toEqual value: 'method', scopes: ['source.ruby'] 239 | expect(tokens[1]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 240 | expect(tokens[2]).toEqual value: 'a', scopes: ['source.ruby'] 241 | expect(tokens[3]).toEqual value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby'] 242 | expect(tokens[4]).toEqual value: 'b', scopes: ['source.ruby'] 243 | expect(tokens[5]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 244 | 245 | 246 | it "tokenizes %() style strings", -> 247 | {tokens} = grammar.tokenizeLine('%(te(s)t)') 248 | 249 | expect(tokens[0]).toEqual value: '%(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 250 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 251 | expect(tokens[2]).toEqual value: '(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 252 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 253 | expect(tokens[4]).toEqual value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 254 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 255 | expect(tokens[6]).toEqual value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 256 | 257 | it "tokenizes %[] style strings", -> 258 | {tokens} = grammar.tokenizeLine('%[te[s]t]') 259 | 260 | expect(tokens[0]).toEqual value: '%[', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 261 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 262 | expect(tokens[2]).toEqual value: '[', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 263 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 264 | expect(tokens[4]).toEqual value: ']', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 265 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 266 | expect(tokens[6]).toEqual value: ']', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 267 | 268 | it "tokenizes %{} style strings", -> 269 | {tokens} = grammar.tokenizeLine('%{te{s}t}') 270 | 271 | expect(tokens[0]).toEqual value: '%{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 272 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 273 | expect(tokens[2]).toEqual value: '{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 274 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 275 | expect(tokens[4]).toEqual value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 276 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 277 | expect(tokens[6]).toEqual value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 278 | 279 | it "tokenizes %<> style strings", -> 280 | {tokens} = grammar.tokenizeLine('%t>') 281 | 282 | expect(tokens[0]).toEqual value: '%<', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 283 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 284 | expect(tokens[2]).toEqual value: '<', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 285 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 286 | expect(tokens[4]).toEqual value: '>', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 287 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 288 | expect(tokens[6]).toEqual value: '>', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 289 | 290 | it "tokenizes %~~ style strings", -> 291 | {tokens} = grammar.tokenizeLine('%~te\\~s\\~t~') 292 | 293 | expect(tokens[0]).toEqual value: '%~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 294 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 295 | expect(tokens[2]).toEqual value: '\\~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'constant.character.escape.ruby'] 296 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 297 | expect(tokens[4]).toEqual value: '\\~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'constant.character.escape.ruby'] 298 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 299 | expect(tokens[6]).toEqual value: '~', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 300 | 301 | it "tokenizes %Q() style strings", -> 302 | {tokens} = grammar.tokenizeLine('%Q(te(s)t)') 303 | 304 | expect(tokens[0]).toEqual value: '%Q(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 305 | expect(tokens[1]).toEqual value: 'te', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 306 | expect(tokens[2]).toEqual value: '(', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 307 | expect(tokens[3]).toEqual value: 's', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 308 | expect(tokens[4]).toEqual value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.section.scope.ruby'] 309 | expect(tokens[5]).toEqual value: 't', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby'] 310 | expect(tokens[6]).toEqual value: ')', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 311 | 312 | it "tokenizes %x!! style strings", -> 313 | {tokens} = grammar.tokenizeLine('%x!\#\{"l" + "s"\}!') 314 | 315 | expect(tokens[0]).toEqual value: '%x!', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.begin.ruby'] 316 | expect(tokens[1]).toEqual value: '#{', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'meta.embedded.line.ruby', 'punctuation.section.embedded.begin.ruby'] 317 | expect(tokens[11]).toEqual value: '}', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'meta.embedded.line.ruby', 'punctuation.section.embedded.end.ruby'] 318 | expect(tokens[12]).toEqual value: '!', scopes: ['source.ruby', 'string.quoted.other.interpolated.ruby', 'punctuation.definition.string.end.ruby'] 319 | 320 | it "tokenizes regular expressions", -> 321 | {tokens} = grammar.tokenizeLine('/test/') 322 | 323 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 324 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 325 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 326 | 327 | {tokens} = grammar.tokenizeLine('/{w}/') 328 | 329 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 330 | expect(tokens[1]).toEqual value: '{w}', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 331 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 332 | 333 | {tokens} = grammar.tokenizeLine('a_method /test/') 334 | 335 | expect(tokens[0]).toEqual value: 'a_method ', scopes: ['source.ruby'] 336 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 337 | expect(tokens[2]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 338 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 339 | 340 | {tokens} = grammar.tokenizeLine('a_method(/test/)') 341 | 342 | expect(tokens[0]).toEqual value: 'a_method', scopes: ['source.ruby'] 343 | expect(tokens[1]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 344 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 345 | expect(tokens[3]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 346 | expect(tokens[4]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 347 | expect(tokens[5]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 348 | 349 | {tokens} = grammar.tokenizeLine('/test/.match("test")') 350 | 351 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 352 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 353 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 354 | expect(tokens[3]).toEqual value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 355 | 356 | {tokens} = grammar.tokenizeLine('foo(4 / 2).split(/c/)') 357 | 358 | expect(tokens[0]).toEqual value: 'foo', scopes: ['source.ruby'] 359 | expect(tokens[1]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 360 | expect(tokens[2]).toEqual value: '4', scopes: ['source.ruby', 'constant.numeric.ruby'] 361 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 362 | expect(tokens[4]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 363 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 364 | expect(tokens[6]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 365 | expect(tokens[7]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 366 | expect(tokens[8]).toEqual value: '.', scopes: ['source.ruby', 'punctuation.separator.method.ruby'] 367 | expect(tokens[9]).toEqual value: 'split', scopes: ['source.ruby'] 368 | expect(tokens[10]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 369 | expect(tokens[11]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 370 | expect(tokens[12]).toEqual value: 'c', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 371 | expect(tokens[13]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 372 | expect(tokens[14]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 373 | 374 | {tokens} = grammar.tokenizeLine('[/test/,3]') 375 | 376 | expect(tokens[0]).toEqual value: '[', scopes: ['source.ruby', 'punctuation.section.array.begin.ruby'] 377 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 378 | expect(tokens[2]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 379 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 380 | expect(tokens[4]).toEqual value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby'] 381 | 382 | {tokens} = grammar.tokenizeLine('[/test/]') 383 | 384 | expect(tokens[0]).toEqual value: '[', scopes: ['source.ruby', 'punctuation.section.array.begin.ruby'] 385 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 386 | expect(tokens[2]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 387 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 388 | 389 | {tokens} = grammar.tokenizeLine('/test/ && 4') 390 | 391 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 392 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 393 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 394 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 395 | 396 | {tokens} = grammar.tokenizeLine('/test/ || 4') 397 | 398 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 399 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 400 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 401 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 402 | 403 | {tokens} = grammar.tokenizeLine('/test/ ? 4 : 3') 404 | 405 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 406 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 407 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 408 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 409 | 410 | {tokens} = grammar.tokenizeLine('/test/ : foo') 411 | 412 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 413 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 414 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 415 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 416 | 417 | {tokens} = grammar.tokenizeLine('{a: /test/}') 418 | 419 | expect(tokens[4]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 420 | expect(tokens[5]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 421 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 422 | 423 | {tokens} = grammar.tokenizeLine('if "test" =~ /test/ then 4 end') 424 | 425 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 426 | expect(tokens[9]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 427 | expect(tokens[10]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 428 | expect(tokens[11]).toEqual value: ' ', scopes: ['source.ruby'] 429 | expect(tokens[12]).toEqual value: 'then', scopes: ['source.ruby', 'keyword.control.ruby'] 430 | 431 | {tokens} = grammar.tokenizeLine('if "test" =~ /test/; 4 end') 432 | 433 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 434 | expect(tokens[9]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 435 | expect(tokens[10]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 436 | expect(tokens[11]).toEqual value: ';', scopes: ['source.ruby', 'punctuation.terminator.statement.ruby'] 437 | 438 | {tokens} = grammar.tokenizeLine('/test/ =~ "test"') 439 | 440 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 441 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 442 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 443 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 444 | expect(tokens[4]).toEqual value: '=~', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 445 | 446 | {tokens} = grammar.tokenizeLine('/test/ !~ "test"') 447 | 448 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 449 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 450 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 451 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 452 | expect(tokens[4]).toEqual value: '!~', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 453 | 454 | {tokens} = grammar.tokenizeLine('/test/ != "test"') 455 | 456 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 457 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 458 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 459 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 460 | expect(tokens[4]).toEqual value: '!=', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 461 | 462 | {tokens} = grammar.tokenizeLine('/test/ == /test/') 463 | 464 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 465 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 466 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 467 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 468 | expect(tokens[4]).toEqual value: '==', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 469 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 470 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 471 | expect(tokens[7]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 472 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 473 | 474 | {tokens} = grammar.tokenizeLine('/test/ === /test/') 475 | 476 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 477 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 478 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 479 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 480 | expect(tokens[4]).toEqual value: '===', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 481 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 482 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 483 | expect(tokens[7]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 484 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 485 | 486 | {tokens} = grammar.tokenizeLine('if false then /test/ else 4 end') 487 | 488 | expect(tokens[4]).toEqual value: 'then', scopes: ['source.ruby', 'keyword.control.ruby'] 489 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 490 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 491 | expect(tokens[7]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 492 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 493 | expect(tokens[9]).toEqual value: ' ', scopes: ['source.ruby'] 494 | expect(tokens[10]).toEqual value: 'else', scopes: ['source.ruby', 'keyword.control.ruby'] 495 | 496 | {tokens} = grammar.tokenizeLine('if false then 4 else /test/ end') 497 | 498 | expect(tokens[8]).toEqual value: 'else', scopes: ['source.ruby', 'keyword.control.ruby'] 499 | expect(tokens[9]).toEqual value: ' ', scopes: ['source.ruby'] 500 | expect(tokens[10]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 501 | expect(tokens[11]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 502 | expect(tokens[12]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 503 | expect(tokens[13]).toEqual value: ' ', scopes: ['source.ruby'] 504 | expect(tokens[14]).toEqual value: 'end', scopes: ['source.ruby', 'keyword.control.ruby'] 505 | 506 | {tokens} = grammar.tokenizeLine('if true then /test/ elsif false then 4 end') 507 | 508 | expect(tokens[4]).toEqual value: 'then', scopes: ['source.ruby', 'keyword.control.ruby'] 509 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 510 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 511 | expect(tokens[7]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 512 | expect(tokens[8]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 513 | expect(tokens[9]).toEqual value: ' ', scopes: ['source.ruby'] 514 | expect(tokens[10]).toEqual value: 'elsif', scopes: ['source.ruby', 'keyword.control.ruby'] 515 | 516 | {tokens} = grammar.tokenizeLine('method /test/ do; end') 517 | 518 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 519 | expect(tokens[2]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 520 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 521 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby'] 522 | expect(tokens[5]).toEqual value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby'] 523 | 524 | {tokens} = grammar.tokenizeLine('/test/ if true') 525 | 526 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 527 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 528 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 529 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 530 | expect(tokens[4]).toEqual value: 'if', scopes: ['source.ruby', 'keyword.control.ruby'] 531 | 532 | {tokens} = grammar.tokenizeLine('/test/ unless true') 533 | 534 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 535 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 536 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 537 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 538 | expect(tokens[4]).toEqual value: 'unless', scopes: ['source.ruby', 'keyword.control.ruby'] 539 | 540 | {tokens} = grammar.tokenizeLine('/test/ while true') 541 | 542 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 543 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 544 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 545 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 546 | expect(tokens[4]).toEqual value: 'while', scopes: ['source.ruby', 'keyword.control.ruby'] 547 | 548 | {tokens} = grammar.tokenizeLine('/test/ until true') 549 | 550 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 551 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 552 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 553 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 554 | expect(tokens[4]).toEqual value: 'until', scopes: ['source.ruby', 'keyword.control.ruby'] 555 | 556 | {tokens} = grammar.tokenizeLine('/test/ or return') 557 | 558 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 559 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 560 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 561 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 562 | expect(tokens[4]).toEqual value: 'or', scopes: ['source.ruby', 'keyword.operator.logical.ruby'] 563 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 564 | expect(tokens[6]).toEqual value: 'return', scopes: ['source.ruby', 'keyword.control.pseudo-method.ruby'] 565 | 566 | {tokens} = grammar.tokenizeLine('/test/ and return') 567 | 568 | expect(tokens[0]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 569 | expect(tokens[1]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 570 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 571 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 572 | expect(tokens[4]).toEqual value: 'and', scopes: ['source.ruby', 'keyword.operator.logical.ruby'] 573 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 574 | expect(tokens[6]).toEqual value: 'return', scopes: ['source.ruby', 'keyword.control.pseudo-method.ruby'] 575 | 576 | {tokens} = grammar.tokenizeLine('{/test/ => 1}') 577 | 578 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 579 | expect(tokens[2]).toEqual value: 'test', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 580 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 581 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby'] 582 | expect(tokens[5]).toEqual value: '=>', scopes: ['source.ruby', 'punctuation.separator.key-value.ruby'] 583 | expect(tokens[6]).toEqual value: ' ', scopes: ['source.ruby'] 584 | expect(tokens[7]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 585 | 586 | it "tokenizes multiline regular expressions", -> 587 | tokens = grammar.tokenizeLines ''' 588 | regexp = / 589 | foo| 590 | bar 591 | /ix 592 | ''' 593 | 594 | expect(tokens[0][0]).toEqual value: 'regexp ', scopes: ['source.ruby'] 595 | expect(tokens[0][1]).toEqual value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby'] 596 | expect(tokens[0][2]).toEqual value: ' ', scopes: ['source.ruby'] 597 | expect(tokens[0][3]).toEqual value: '/', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 598 | expect(tokens[1][0]).toEqual value: ' foo|', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 599 | expect(tokens[2][0]).toEqual value: ' bar', scopes: ['source.ruby', 'string.regexp.interpolated.ruby'] 600 | expect(tokens[3][0]).toEqual value: '/ix', scopes: ['source.ruby', 'string.regexp.interpolated.ruby', 'punctuation.section.regexp.ruby'] 601 | 602 | it "tokenizes the / arithmetic operator", -> 603 | {tokens} = grammar.tokenizeLine('call/me/maybe') 604 | expect(tokens[0]).toEqual value: 'call', scopes: ['source.ruby'] 605 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 606 | expect(tokens[2]).toEqual value: 'me', scopes: ['source.ruby'] 607 | expect(tokens[3]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 608 | expect(tokens[4]).toEqual value: 'maybe', scopes: ['source.ruby'] 609 | 610 | {tokens} = grammar.tokenizeLine('(1+2)/3/4') 611 | expect(tokens[0]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 612 | expect(tokens[1]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 613 | expect(tokens[2]).toEqual value: '+', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 614 | expect(tokens[3]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 615 | expect(tokens[4]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 616 | expect(tokens[5]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 617 | expect(tokens[6]).toEqual value: '3', scopes: ['source.ruby', 'constant.numeric.ruby'] 618 | expect(tokens[7]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 619 | expect(tokens[8]).toEqual value: '4', scopes: ['source.ruby', 'constant.numeric.ruby'] 620 | 621 | {tokens} = grammar.tokenizeLine('1 / 2 / 3') 622 | expect(tokens[0]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 623 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby'] 624 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 625 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 626 | expect(tokens[4]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 627 | expect(tokens[5]).toEqual value: ' ', scopes: ['source.ruby'] 628 | expect(tokens[6]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 629 | expect(tokens[7]).toEqual value: ' ', scopes: ['source.ruby'] 630 | expect(tokens[8]).toEqual value: '3', scopes: ['source.ruby', 'constant.numeric.ruby'] 631 | 632 | {tokens} = grammar.tokenizeLine('1/ 2 / 3') 633 | expect(tokens[0]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 634 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 635 | expect(tokens[2]).toEqual value: ' ', scopes: ['source.ruby'] 636 | expect(tokens[3]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 637 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby'] 638 | expect(tokens[5]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 639 | expect(tokens[6]).toEqual value: ' ', scopes: ['source.ruby'] 640 | expect(tokens[7]).toEqual value: '3', scopes: ['source.ruby', 'constant.numeric.ruby'] 641 | 642 | {tokens} = grammar.tokenizeLine('1 / 2/ 3') 643 | expect(tokens[0]).toEqual value: '1', scopes: ['source.ruby', 'constant.numeric.ruby'] 644 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby'] 645 | expect(tokens[2]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 646 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby'] 647 | expect(tokens[4]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 648 | expect(tokens[5]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 649 | expect(tokens[6]).toEqual value: ' ', scopes: ['source.ruby'] 650 | expect(tokens[7]).toEqual value: '3', scopes: ['source.ruby', 'constant.numeric.ruby'] 651 | 652 | {tokens} = grammar.tokenizeLine('x / 2; x /= 2') 653 | expect(tokens[1]).toEqual value: '/', scopes: ['source.ruby', 'keyword.operator.arithmetic.ruby'] 654 | expect(tokens[2]).toEqual value: ' ', scopes: ['source.ruby'] 655 | expect(tokens[3]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 656 | expect(tokens[4]).toEqual value: ';', scopes: ['source.ruby', 'punctuation.terminator.statement.ruby'] 657 | expect(tokens[6]).toEqual value: '/=', scopes: ['source.ruby', 'keyword.operator.assignment.augmented.ruby'] 658 | expect(tokens[7]).toEqual value: ' ', scopes: ['source.ruby'] 659 | expect(tokens[8]).toEqual value: '2', scopes: ['source.ruby', 'constant.numeric.ruby'] 660 | 661 | it "tokenizes 'not' when used as method name", -> 662 | {tokens} = grammar.tokenizeLine('foo.not(bar)') 663 | expect(tokens[2]).toEqual value: 'not', scopes: ['source.ruby'] 664 | 665 | {tokens} = grammar.tokenizeLine('not?(Array)') 666 | expect(tokens[0]).toEqual value: 'not?', scopes: ['source.ruby'] 667 | 668 | it "tokenizes 'not' as logical operator", -> 669 | {tokens} = grammar.tokenizeLine('not true') 670 | expect(tokens[0]).toEqual value: 'not', scopes: ['source.ruby', 'keyword.operator.logical.ruby'] 671 | 672 | it "tokenizes ! when used in method name", -> 673 | {tokens} = grammar.tokenizeLine('sort!') 674 | expect(tokens[0]).toEqual value: 'sort!', scopes: ['source.ruby'] 675 | 676 | it "tokenizes ! as logical operator", -> 677 | {tokens} = grammar.tokenizeLine('!foo') 678 | expect(tokens[0]).toEqual value: '!', scopes: ['source.ruby', 'keyword.operator.logical.ruby'] 679 | 680 | it "tokenizes != as comparison operator", -> 681 | {tokens} = grammar.tokenizeLine('foo != bar') 682 | expect(tokens[1]).toEqual value: '!=', scopes: ['source.ruby', 'keyword.operator.comparison.ruby'] 683 | 684 | it "tokenizes yard documentation comments", -> 685 | {tokens} = grammar.tokenizeLine('# @private') 686 | expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 687 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 688 | expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 689 | expect(tokens[3]).toEqual value: 'private', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 690 | 691 | tokens = grammar.tokenizeLines ''' 692 | # @deprecated Because I said so, 693 | # end of discussion 694 | ''' 695 | expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 696 | expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 697 | expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 698 | expect(tokens[0][3]).toEqual value: 'deprecated', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 699 | expect(tokens[0][4]).toEqual value: ' Because I said so,', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 700 | expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby'] 701 | expect(tokens[1][1]).toEqual value: ' end of discussion', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 702 | 703 | tokens = grammar.tokenizeLines ''' 704 | # @raise [AccountBalanceError] if the account does not have 705 | # sufficient funds to perform the transaction 706 | ''' 707 | expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 708 | expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 709 | expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 710 | expect(tokens[0][3]).toEqual value: 'raise', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 711 | expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 712 | expect(tokens[0][5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 713 | expect(tokens[0][6]).toEqual value: 'AccountBalanceError', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 714 | expect(tokens[0][7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 715 | expect(tokens[0][8]).toEqual value: ' if the account does not have', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 716 | expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby'] 717 | expect(tokens[1][1]).toEqual value: ' sufficient funds to perform the transaction', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 718 | 719 | tokens = grammar.tokenizeLines ''' 720 | # @param value [Object] describe value param in a long way which 721 | # makes it multiline 722 | ''' 723 | expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 724 | expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 725 | expect(tokens[0][2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 726 | expect(tokens[0][3]).toEqual value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 727 | expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 728 | expect(tokens[0][5]).toEqual value: 'value', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.parameter.yard.ruby'] 729 | expect(tokens[0][6]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 730 | expect(tokens[0][7]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 731 | expect(tokens[0][8]).toEqual value: 'Object', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 732 | expect(tokens[0][9]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 733 | expect(tokens[0][10]).toEqual value: ' describe value param in a long way which', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 734 | expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby'] 735 | expect(tokens[1][1]).toEqual value: ' makes it multiline', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 736 | 737 | {tokens} = grammar.tokenizeLine('# @param [Bar] Baz') 738 | expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 739 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 740 | expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 741 | expect(tokens[3]).toEqual value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 742 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 743 | expect(tokens[5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 744 | expect(tokens[6]).toEqual value: 'Bar', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 745 | expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 746 | expect(tokens[8]).toEqual value: ' Baz', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 747 | 748 | {tokens} = grammar.tokenizeLine('# @return [Array#[](0), Array] comment') 749 | expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 750 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 751 | expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 752 | expect(tokens[3]).toEqual value: 'return', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 753 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 754 | expect(tokens[5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 755 | expect(tokens[6]).toEqual value: 'Array#[](0), Array', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 756 | expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 757 | expect(tokens[8]).toEqual value: ' comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 758 | 759 | {tokens} = grammar.tokenizeLine('# @param [Array#[](0), Array] comment') 760 | expect(tokens[0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 761 | expect(tokens[1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 762 | expect(tokens[2]).toEqual value: '@', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 763 | expect(tokens[3]).toEqual value: 'param', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 764 | expect(tokens[4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 765 | expect(tokens[5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 766 | expect(tokens[6]).toEqual value: 'Array#[](0), Array', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 767 | expect(tokens[7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 768 | expect(tokens[8]).toEqual value: ' comment', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 769 | 770 | tokens = grammar.tokenizeLines ''' 771 | # @!attribute [r] count the number of items 772 | # present in the list 773 | ''' 774 | expect(tokens[0][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'punctuation.definition.comment.ruby'] 775 | expect(tokens[0][1]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby'] 776 | expect(tokens[0][2]).toEqual value: '@!', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.punctuation.yard.ruby'] 777 | expect(tokens[0][3]).toEqual value: 'attribute', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.keyword.yard.ruby'] 778 | expect(tokens[0][4]).toEqual value: ' ', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby'] 779 | expect(tokens[0][5]).toEqual value: '[', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 780 | expect(tokens[0][6]).toEqual value: 'r', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby'] 781 | expect(tokens[0][7]).toEqual value: ']', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.yard.ruby', 'comment.line.type.yard.ruby', 'comment.line.punctuation.yard.ruby'] 782 | expect(tokens[0][8]).toEqual value: ' count the number of items', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 783 | expect(tokens[1][0]).toEqual value: '#', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby', 'punctuation.definition.comment.ruby'] 784 | expect(tokens[1][1]).toEqual value: ' present in the list', scopes: ['source.ruby', 'comment.line.number-sign.ruby', 'comment.line.string.yard.ruby'] 785 | 786 | it "tokenizes a method with *args properly", -> 787 | {tokens} = grammar.tokenizeLine('def method(*args)') 788 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 789 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 790 | expect(tokens[3]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 791 | expect(tokens[4]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 792 | expect(tokens[5]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 793 | expect(tokens[6]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 794 | 795 | {tokens} = grammar.tokenizeLine('def method(args)') 796 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 797 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 798 | expect(tokens[3]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 799 | expect(tokens[4]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 800 | expect(tokens[5]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 801 | 802 | {tokens} = grammar.tokenizeLine('def method *args') 803 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 804 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 805 | expect(tokens[3]).toEqual value: ' ', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby'] 806 | expect(tokens[4]).toEqual value: '*', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'storage.type.variable.ruby'] 807 | expect(tokens[5]).toEqual value: 'args', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'variable.parameter.function.ruby'] 808 | 809 | it "tokenizes a method with (symbol: arg) properly", -> 810 | {tokens} = grammar.tokenizeLine('def method(red: 2)') 811 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 812 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 813 | expect(tokens[3]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 814 | expect(tokens[4]).toEqual value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 815 | expect(tokens[7]).toEqual value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 816 | 817 | it "tokenizes a method with symbol: arg (no paren) properly", -> 818 | {tokens} = grammar.tokenizeLine('def method red: 2') 819 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 820 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 821 | expect(tokens[4]).toEqual value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 822 | expect(tokens[7]).toEqual value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 823 | 824 | it "tokenizes a method with (symbol: arg(paren), symbol: arg2(paren)...) properly", -> 825 | {tokens} = grammar.tokenizeLine('def method(red: rand(2), green: rand(3), blue: rand(4))') 826 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 827 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 828 | expect(tokens[3]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.definition.parameters.ruby'] 829 | expect(tokens[4]).toEqual value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 830 | expect(tokens[7]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 831 | expect(tokens[8]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 832 | expect(tokens[9]).toEqual value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 833 | expect(tokens[10]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 834 | expect(tokens[11]).toEqual value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby'] 835 | expect(tokens[13]).toEqual value: 'green', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 836 | expect(tokens[16]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 837 | expect(tokens[17]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 838 | expect(tokens[18]).toEqual value: '3', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 839 | expect(tokens[19]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 840 | expect(tokens[20]).toEqual value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby'] 841 | expect(tokens[22]).toEqual value: 'blue', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 842 | expect(tokens[25]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 843 | expect(tokens[26]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 844 | expect(tokens[27]).toEqual value: '4', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 845 | expect(tokens[28]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 846 | 847 | it "tokenizes a method with symbol: arg(paren), symbol: arg2(paren)... (no outer parens) properly", -> 848 | {tokens} = grammar.tokenizeLine('def method red: rand(2), green: rand(3), blue: rand(4)') 849 | expect(tokens[0]).toEqual value: 'def', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'keyword.control.def.ruby'] 850 | expect(tokens[2]).toEqual value: 'method', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'entity.name.function.ruby'] 851 | expect(tokens[4]).toEqual value: 'red', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 852 | expect(tokens[7]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 853 | expect(tokens[8]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 854 | expect(tokens[9]).toEqual value: '2', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 855 | expect(tokens[10]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 856 | expect(tokens[11]).toEqual value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby'] 857 | expect(tokens[13]).toEqual value: 'green', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 858 | expect(tokens[16]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 859 | expect(tokens[17]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 860 | expect(tokens[18]).toEqual value: '3', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 861 | expect(tokens[19]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 862 | expect(tokens[20]).toEqual value: ',', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.separator.delimiter.ruby'] 863 | expect(tokens[22]).toEqual value: 'blue', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.other.symbol.hashkey.parameter.function.ruby'] 864 | expect(tokens[25]).toEqual value: 'rand', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'support.function.kernel.ruby'] 865 | expect(tokens[26]).toEqual value: '(', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 866 | expect(tokens[27]).toEqual value: '4', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'constant.numeric.ruby'] 867 | expect(tokens[28]).toEqual value: ')', scopes: ['source.ruby', 'meta.function.method.with-arguments.ruby', 'punctuation.section.function.ruby'] 868 | 869 | it "tokenizes a stabby lambda properly", -> 870 | {tokens} = grammar.tokenizeLine('method_name -> { puts "A message"} do') 871 | expect(tokens[1]).toEqual value: '->', scopes: ['source.ruby', 'support.function.kernel.arrow.ruby'] 872 | 873 | it "tokenizes a simple do block properly", -> 874 | {tokens} = grammar.tokenizeLine('do |foo| ') 875 | expect(tokens[0]).toEqual value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby'] 876 | expect(tokens[2]).toEqual value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby'] 877 | expect(tokens[3]).toEqual value: 'foo', scopes: ['source.ruby', 'variable.other.block.ruby'] 878 | expect(tokens[4]).toEqual value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby'] 879 | 880 | it "tokenizes a complex do block properly", -> 881 | {tokens} = grammar.tokenizeLine('do |key = (a || b), hash = config, create: false|') 882 | expect(tokens[0]).toEqual value: 'do', scopes: ['source.ruby', 'keyword.control.start-block.ruby'] 883 | expect(tokens[2]).toEqual value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby'] 884 | expect(tokens[3]).toEqual value: 'key', scopes: ['source.ruby', 'variable.other.block.ruby'] 885 | expect(tokens[5]).toEqual value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby'] 886 | expect(tokens[7]).toEqual value: '(', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 887 | expect(tokens[8]).toEqual value: 'a', scopes: ['source.ruby', 'variable.other.block.ruby'] 888 | expect(tokens[10]).toEqual value: '||', scopes: ['source.ruby', 'keyword.operator.logical.ruby'] 889 | expect(tokens[12]).toEqual value: 'b', scopes: ['source.ruby', 'variable.other.block.ruby'] 890 | expect(tokens[13]).toEqual value: ')', scopes: ['source.ruby', 'punctuation.section.function.ruby'] 891 | expect(tokens[14]).toEqual value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby'] 892 | expect(tokens[16]).toEqual value: 'hash', scopes: ['source.ruby', 'variable.other.block.ruby'] 893 | expect(tokens[18]).toEqual value: '=', scopes: ['source.ruby', 'keyword.operator.assignment.ruby'] 894 | expect(tokens[20]).toEqual value: 'config', scopes: ['source.ruby', 'variable.other.block.ruby'] 895 | expect(tokens[21]).toEqual value: ',', scopes: ['source.ruby', 'punctuation.separator.delimiter.ruby'] 896 | expect(tokens[23]).toEqual value: 'create', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby'] 897 | expect(tokens[24]).toEqual value: ':', scopes: ['source.ruby', 'constant.other.symbol.hashkey.ruby', 'punctuation.definition.constant.hashkey.ruby'] 898 | expect(tokens[26]).toEqual value: 'false', scopes: ['source.ruby', 'constant.language.boolean.ruby'] 899 | expect(tokens[27]).toEqual value: '|', scopes: ['source.ruby', 'punctuation.separator.variable.ruby'] 900 | 901 | it "does not erroneously tokenize a variable ending in `do` followed by a pipe as a block", -> 902 | {tokens} = grammar.tokenizeLine('sudo ||= true') 903 | expect(tokens[0]).toEqual value: 'sudo ', scopes: ['source.ruby'] 904 | expect(tokens[1]).toEqual value: '||=', scopes: ['source.ruby', 'keyword.operator.assignment.augmented.ruby'] 905 | expect(tokens[3]).toEqual value: 'true', scopes: ['source.ruby', 'constant.language.boolean.ruby'] 906 | 907 | it "tokenizes <<- heredoc", -> 908 | lines = grammar.tokenizeLines('<<-EOS\nThis is text\nEOS') 909 | expect(lines[0][0]).toEqual value: '<<-EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 910 | expect(lines[2][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 911 | 912 | it "tokenizes <<~ Ruby 2.3.0 squiggly heredoc", -> 913 | lines = grammar.tokenizeLines('<<~EOS\nThis is text\nEOS') 914 | expect(lines[0][0]).toEqual value: '<<~EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 915 | expect(lines[2][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 916 | 917 | it "tokenizes quoted heredoc", -> 918 | # Double-quoted heredoc: 919 | lines = grammar.tokenizeLines('<<~"EOS"\nThis is text\nEOS') 920 | expect(lines[0][0]).toEqual value: '<<~"EOS"', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 921 | expect(lines[2][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 922 | # Single-quoted heredoc: 923 | lines = grammar.tokenizeLines('<<~\'EOS\'\nThis is text\nEOS') 924 | expect(lines[0][0]).toEqual value: '<<~\'EOS\'', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 925 | expect(lines[2][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 926 | # Backtick-quoted heredoc: 927 | lines = grammar.tokenizeLines('<<~`EOS`\nThis is text\nEOS') 928 | expect(lines[0][0]).toEqual value: '<<~`EOS`', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 929 | expect(lines[2][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 930 | 931 | it "tokenizes heredoc which includes identifier in end of a line", -> 932 | lines = grammar.tokenizeLines('<<-EOS\nThis is text\nThis is Not EOS\nEOS') 933 | expect(lines[0][0]).toEqual value: '<<-EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.begin.ruby'] 934 | expect(lines[3][0]).toEqual value: 'EOS', scopes: ['source.ruby', 'string.unquoted.heredoc.ruby', 'punctuation.definition.string.end.ruby'] 935 | 936 | it "tokenizes Kernel support functions autoload? and exit!", -> 937 | lines = grammar.tokenizeLines('p autoload?(:test)\nexit!\nat_exit!') 938 | expect(lines[0][2]).toEqual value: 'autoload?', scopes: ['source.ruby', 'support.function.kernel.ruby'] 939 | expect(lines[1][0]).toEqual value: 'exit!', scopes: ['source.ruby', 'support.function.kernel.ruby'] 940 | expect(lines[2][0]).toEqual value: 'at_exit!', scopes: ['source.ruby'] 941 | 942 | it "tokenizes iterator? the same way as block_given?", -> 943 | lines = grammar.tokenizeLines('p iterator?\np block_given?') 944 | expect(lines[0][2].value).toEqual 'iterator?' 945 | expect(lines[1][2].value).toEqual 'block_given?' 946 | expect(lines[0][2].scopes).toEqual lines[1][2].scopes 947 | 948 | describe "firstLineMatch", -> 949 | it "recognises interpreter directives", -> 950 | valid = """ 951 | #!/usr/sbin/ruby foo 952 | #!/usr/bin/rake foo=bar/ 953 | #!/usr/sbin/jruby 954 | #!/usr/sbin/rbx foo bar baz 955 | #!/usr/bin/rake perl 956 | #!/usr/bin/macruby bin/perl 957 | #!/usr/bin/rbx 958 | #!/bin/rbx 959 | #!/bin/env ruby_executable_hooks 960 | #!/usr/bin/ruby --script=usr/bin 961 | #! /usr/bin/env A=003 B=149 C=150 D=xzd E=base64 F=tar G=gz H=head I=tail rbx 962 | #!\t/usr/bin/env --foo=bar ruby --quu=quux 963 | #! /usr/bin/ruby 964 | #!/usr/bin/env ruby 965 | """ 966 | for line in valid.split /\n/ 967 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 968 | 969 | invalid = """ 970 | \x20#!/usr/sbin/ruby 971 | \t#!/usr/sbin/rake 972 | #!/usr/bin/env-ruby/node-env/ 973 | #!/usr/bin/env-ruby 974 | #! /usr/binrake 975 | #!\t/usr/bin/env --ruby=bar 976 | """ 977 | for line in invalid.split /\n/ 978 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 979 | 980 | it "recognises Emacs modelines", -> 981 | valid = """ 982 | #-*- Ruby -*- 983 | #-*- mode: Ruby -*- 984 | /* -*-ruby-*- */ 985 | // -*- RUBY -*- 986 | /* -*- mode:RUBY -*- */ 987 | // -*- font:bar;mode:Ruby -*- 988 | // -*- font:bar;mode:ruby;foo:bar; -*- 989 | // -*-font:mode;mode:Ruby-*- 990 | // -*- foo:bar mode: ruby bar:baz -*- 991 | " -*-foo:bar;mode:ruby;bar:foo-*- "; 992 | " -*-font-mode:foo;mode:ruby;foo-bar:quux-*-" 993 | "-*-font:x;foo:bar; mode : ruby; bar:foo;foooooo:baaaaar;fo:ba;-*-"; 994 | "-*- font:x;foo : bar ; mode : RUBY ; bar : foo ; foooooo:baaaaar;fo:ba-*-"; 995 | """ 996 | for line in valid.split /\n/ 997 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 998 | 999 | invalid = """ 1000 | /* --*ruby-*- */ 1001 | /* -*-- ruby -*- 1002 | /* -*- -- RUBY -*- 1003 | /* -*- RUBY -;- -*- 1004 | // -*- iRUBY -*- 1005 | // -*- ruby; -*- 1006 | // -*- ruby-stuff -*- 1007 | /* -*- model:ruby -*- 1008 | /* -*- indent-mode:ruby -*- 1009 | // -*- font:mode;Ruby -*- 1010 | // -*- mode: -*- Ruby 1011 | // -*- mode: i-named-my-dog-ruby -*- 1012 | // -*-font:mode;mode:ruby--*- 1013 | """ 1014 | for line in invalid.split /\n/ 1015 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 1016 | 1017 | it "recognises Vim modelines", -> 1018 | valid = """ 1019 | vim: se filetype=ruby: 1020 | # vim: se ft=ruby: 1021 | # vim: set ft=Ruby: 1022 | # vim: set filetype=RUBY: 1023 | # vim: ft=RUBY 1024 | # vim: syntax=Ruby 1025 | # vim: se syntax=ruBy: 1026 | # ex: syntax=rUBy 1027 | # vim:ft=RubY 1028 | # vim600: ft=ruby 1029 | # vim>600: set ft=ruby: 1030 | # vi:noai:sw=3 ts=6 ft=ruby 1031 | # vi::::::::::noai:::::::::::: ft=ruby 1032 | # vim:ts=4:sts=4:sw=4:noexpandtab:ft=ruby 1033 | # vi:: noai : : : : sw =3 ts =6 ft =ruby 1034 | # vim: ts=4: pi sts=4: ft=ruby: noexpandtab: sw=4: 1035 | # vim: ts=4 sts=4: ft=ruby noexpandtab: 1036 | # vim:noexpandtab sts=4 ft=ruby ts=4 1037 | # vim:noexpandtab:ft=RUBY 1038 | # vim:ts=4:sts=4 ft=ruby:noexpandtab:\x20 1039 | # vim:noexpandtab titlestring=hi\|there\\\\ ft=ruby ts=4 1040 | """ 1041 | for line in valid.split /\n/ 1042 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).not.toBeNull() 1043 | 1044 | invalid = """ 1045 | ex: se filetype=ruby: 1046 | _vi: se filetype=ruby: 1047 | vi: se filetype=ruby 1048 | # vim set ft=rubyy 1049 | # vim: soft=ruby 1050 | # vim: clean-syntax=ruby: 1051 | # vim set ft=ruby: 1052 | # vim: setft=ruby: 1053 | # vim: se ft=ruby backupdir=tmp 1054 | # vim: set ft=ruby set cmdheight=1 1055 | # vim:noexpandtab sts:4 ft:ruby ts:4 1056 | # vim:noexpandtab titlestring=hi\\|there\\ ft=ruby ts=4 1057 | # vim:noexpandtab titlestring=hi\\|there\\\\\\ ft=ruby ts=4 1058 | """ 1059 | for line in invalid.split /\n/ 1060 | expect(grammar.firstLineRegex.scanner.findNextMatchSync(line)).toBeNull() 1061 | -------------------------------------------------------------------------------- /spec/tree-sitter-spec.js: -------------------------------------------------------------------------------- 1 | const dedent = require('dedent') 2 | 3 | describe('Tree-sitter Ruby grammar', () => { 4 | beforeEach(async () => { 5 | atom.config.set('core.useTreeSitterParsers', true) 6 | await atom.packages.activatePackage('language-ruby') 7 | }) 8 | 9 | it('tokenizes symbols', async () => { 10 | const editor = await atom.workspace.open('foo.rb') 11 | 12 | editor.setText(dedent` 13 | :foo 14 | %i(foo) 15 | `) 16 | 17 | expect(editor.scopeDescriptorForBufferPosition([0, 1]).toString()).toBe( 18 | '.source.ruby .constant.other.symbol' 19 | ) 20 | 21 | expect(editor.scopeDescriptorForBufferPosition([1, 3]).toString()).toBe( 22 | '.source.ruby .constant.other.symbol' 23 | ) 24 | }) 25 | 26 | it('tokenizes visibility modifiers', async () => { 27 | const editor = await atom.workspace.open('foo.rb') 28 | 29 | editor.setText(dedent` 30 | public 31 | protected 32 | private 33 | 34 | public def foo; end 35 | protected def bar; end 36 | private def baz; end 37 | `) 38 | 39 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( 40 | '.source.ruby .keyword.other.special-method' 41 | ) 42 | expect(editor.scopeDescriptorForBufferPosition([1, 0]).toString()).toBe( 43 | '.source.ruby .keyword.other.special-method' 44 | ) 45 | expect(editor.scopeDescriptorForBufferPosition([2, 0]).toString()).toBe( 46 | '.source.ruby .keyword.other.special-method' 47 | ) 48 | expect(editor.scopeDescriptorForBufferPosition([4, 0]).toString()).toBe( 49 | '.source.ruby .keyword.other.special-method' 50 | ) 51 | expect(editor.scopeDescriptorForBufferPosition([5, 0]).toString()).toBe( 52 | '.source.ruby .keyword.other.special-method' 53 | ) 54 | expect(editor.scopeDescriptorForBufferPosition([6, 0]).toString()).toBe( 55 | '.source.ruby .keyword.other.special-method' 56 | ) 57 | }) 58 | 59 | it('tokenizes keyword predicates', async () => { 60 | const editor = await atom.workspace.open('foo.rb') 61 | 62 | editor.setText(dedent` 63 | defined?(:thing) 64 | block_given? 65 | iterator? 66 | `) 67 | 68 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( 69 | '.source.ruby .keyword.control' 70 | ) 71 | expect(editor.scopeDescriptorForBufferPosition([1, 0]).toString()).toBe( 72 | '.source.ruby .keyword.control' 73 | ) 74 | expect(editor.scopeDescriptorForBufferPosition([2, 0]).toString()).toBe( 75 | '.source.ruby .keyword.control' 76 | ) 77 | }) 78 | 79 | it('tokenizes alias definitions', async () => { 80 | const editor = await atom.workspace.open('foo.rb') 81 | 82 | editor.setText(dedent` 83 | alias_method :name, :full_name 84 | alias name full_name 85 | `) 86 | 87 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( 88 | '.source.ruby .keyword.control' 89 | ) 90 | expect(editor.scopeDescriptorForBufferPosition([1, 0]).toString()).toBe( 91 | '.source.ruby .keyword.control' 92 | ) 93 | }) 94 | 95 | it('tokenizes keywords', async () => { 96 | const editor = await atom.workspace.open('foo.rb') 97 | 98 | editor.setText(dedent` 99 | super 100 | undef foo 101 | `) 102 | 103 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( 104 | '.source.ruby .keyword.control' 105 | ) 106 | 107 | expect(editor.scopeDescriptorForBufferPosition([1, 0]).toString()).toBe( 108 | '.source.ruby .keyword.control' 109 | ) 110 | }) 111 | 112 | it('tokenizes variable in assignment expressions', async () => { 113 | const editor = await atom.workspace.open('foo.rb') 114 | editor.setText(dedent` 115 | a = 10 116 | `) 117 | 118 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).toBe( 119 | '.source.ruby .variable' 120 | ) 121 | }) 122 | 123 | it('does not tokenizes method call in assignment expressions', async () => { 124 | const editor = await atom.workspace.open('foo.rb') 125 | editor.setText(dedent` 126 | foo() = 10 127 | `) 128 | 129 | expect(editor.scopeDescriptorForBufferPosition([0, 0]).toString()).not.toBe( 130 | '.source.ruby .variable' 131 | ) 132 | }) 133 | }) 134 | --------------------------------------------------------------------------------