diff --git a/Gruntfile.coffee b/Gruntfile.coffee index c42a15b8c..024c01e48 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -11,6 +11,10 @@ packageJson = require './package.json' # TODO Remove once all repositories are public process.env.ATOM_ACCESS_TOKEN ?= '362295be4c5258d3f7b967bbabae662a455ca2a7' +# Shim harmony collections in case grunt was invoked without harmony +# collections enabled +_.extend(global, require('harmony-collections')) unless global.WeakMap? + module.exports = (grunt) -> if not grunt.option('verbose') grunt.log.writeln = (args...) -> grunt.log diff --git a/package.json b/package.json index 5b1b98edb..f15021933 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "coffeestack": "0.6.0", "diff": "git://github.com/benogle/jsdiff.git", "emissary": "0.19.0", - "first-mate": "0.5.0", + "first-mate": "0.10.0", "fs-plus": "0.13.0", "fuzzaldrin": "0.1.0", "git-utils": "0.29.0", @@ -71,7 +71,8 @@ "unzip": "~0.1.9", "rcedit": "~0.1.2", "rimraf": "~2.2.2", - "github-releases": "~0.2.0" + "github-releases": "~0.2.0", + "harmony-collections": "~0.3.8" }, "packageDependencies": { "atom-dark-syntax": "0.10.0", @@ -110,7 +111,7 @@ "release-notes": "0.15.0", "settings-view": "0.52.0", "snippets": "0.17.0", - "spell-check": "0.17.0", + "spell-check": "0.18.0", "status-bar": "0.27.0", "styleguide": "0.19.0", "symbols-view": "0.27.0", diff --git a/script/bootstrap b/script/bootstrap index b666fd8d8..87c18f88b 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --harmony_collections var safeExec = require('./utils/child-process-wrapper.js').safeExec; var fs = require('fs'); var path = require('path'); diff --git a/script/build b/script/build index bb65d7607..b2022c6ae 100755 --- a/script/build +++ b/script/build @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --harmony_collections var cp = require('./utils/child-process-wrapper.js'); var path = require('path'); diff --git a/script/cibuild b/script/cibuild index f79fe7f40..8999f0af9 100755 --- a/script/cibuild +++ b/script/cibuild @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --harmony_collections var cp = require('./utils/child-process-wrapper.js'); var fs = require('fs'); var path = require('path'); diff --git a/script/clean b/script/clean index 859efb00c..1c6590ae3 100755 --- a/script/clean +++ b/script/clean @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --harmony_collections var cp = require('./utils/child-process-wrapper.js'); var path = require('path'); var os = require('os'); diff --git a/script/test b/script/test index 2c3b37147..cb32a470b 100755 --- a/script/test +++ b/script/test @@ -1,4 +1,4 @@ -#!/usr/bin/env node +#!/usr/bin/env node --harmony_collections var safeExec = require('./utils/child-process-wrapper.js').safeExec; var path = require('path'); diff --git a/spec/editor-spec.coffee b/spec/editor-spec.coffee index a770214aa..0a93eb91b 100644 --- a/spec/editor-spec.coffee +++ b/spec/editor-spec.coffee @@ -2698,3 +2698,55 @@ describe "Editor", -> expect(editor.getCursorBufferPosition()).toEqual [0, 2] editor.moveCursorLeft() expect(editor.getCursorBufferPosition()).toEqual [0, 0] + + describe "when the editor's grammar has an injection selector", -> + beforeEach -> + atom.packages.activatePackage('language-text', sync: true) + atom.packages.activatePackage('language-javascript', sync: true) + + it "includes the grammar's patterns when the selector matches the current scope in other grammars", -> + atom.packages.activatePackage('language-hyperlink', sync: true) + grammar = atom.syntax.selectGrammar("text.js") + {tokens} = grammar.tokenizeLine("var i; // http://github.com") + + expect(tokens[0].value).toBe "var" + expect(tokens[0].scopes).toEqual ["source.js", "storage.modifier.js"] + + expect(tokens[6].value).toBe "http://github.com" + expect(tokens[6].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"] + + describe "when the grammar is added", -> + it "retokenizes existing buffers that contain tokens that match the injection selector", -> + editor = atom.project.openSync('sample.js') + editor.setText("// http://github.com") + + {tokens} = editor.lineForScreenRow(0) + expect(tokens[1].value).toBe " http://github.com" + expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] + + atom.packages.activatePackage('language-hyperlink', sync: true) + + {tokens} = editor.lineForScreenRow(0) + expect(tokens[2].value).toBe "http://github.com" + expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"] + + describe "when the grammar is updated", -> + it "retokenizes existing buffers that contain tokens that match the injection selector", -> + editor = atom.project.openSync('sample.js') + editor.setText("// SELECT * FROM OCTOCATS") + + {tokens} = editor.lineForScreenRow(0) + expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" + expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] + + atom.packages.activatePackage('package-with-injection-selector', sync: true) + + {tokens} = editor.lineForScreenRow(0) + expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS" + expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"] + + atom.packages.activatePackage('language-sql', sync: true) + + {tokens} = editor.lineForScreenRow(0) + expect(tokens[2].value).toBe "SELECT" + expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"] diff --git a/spec/fixtures/packages/package-with-injection-selector/grammars/grammar.cson b/spec/fixtures/packages/package-with-injection-selector/grammars/grammar.cson new file mode 100644 index 000000000..3cee5379e --- /dev/null +++ b/spec/fixtures/packages/package-with-injection-selector/grammars/grammar.cson @@ -0,0 +1,4 @@ +'name': 'test' +'scopeName': 'source.test' +'injectionSelector': 'comment' +'patterns': [{'include': 'source.sql'}] diff --git a/spec/project-spec.coffee b/spec/project-spec.coffee index 5f199b575..36de21747 100644 --- a/spec/project-spec.coffee +++ b/spec/project-spec.coffee @@ -403,6 +403,7 @@ describe "Project", -> range: [[2, 6], [2, 11]] it "works on evil filenames", -> + platform.generateEvilFiles() atom.project.setPath(path.join(__dirname, 'fixtures', 'evil-files')) paths = [] matches = [] diff --git a/spec/spec-helper-platform.coffee b/spec/spec-helper-platform.coffee index d7d7de10b..90c5e7a5d 100644 --- a/spec/spec-helper-platform.coffee +++ b/spec/spec-helper-platform.coffee @@ -1,8 +1,6 @@ path = require 'path' fs = require 'fs-plus' -{_} = require 'atom' - ## Platform specific helpers module.exports = # Public: Returns true if being run from within Windows @@ -18,20 +16,20 @@ module.exports = fs.removeSync(evilFilesPath) if fs.existsSync(evilFilesPath) fs.mkdirSync(evilFilesPath) - if (@isWindows()) + if @isWindows() filenames = [ - "a_file_with_utf8.txt", - "file with spaces.txt", + "a_file_with_utf8.txt" + "file with spaces.txt" "utfa\u0306.md" ] else filenames = [ - "a_file_with_utf8.txt", - "file with spaces.txt", - "goddam\nnewlines", - "quote\".txt", + "a_file_with_utf8.txt" + "file with spaces.txt" + "goddam\nnewlines" + "quote\".txt" "utfa\u0306.md" ] for filename in filenames - fd = fs.writeFileSync(path.join(evilFilesPath, filename), 'evil file!', flag: 'w') + fs.writeFileSync(path.join(evilFilesPath, filename), 'evil file!', flag: 'w') diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index 618f81503..59766b88d 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -13,11 +13,8 @@ Editor = require '../src/editor' EditorView = require '../src/editor-view' TokenizedBuffer = require '../src/tokenized-buffer' pathwatcher = require 'pathwatcher' -platform = require './spec-helper-platform' clipboard = require 'clipboard' -platform.generateEvilFiles() - atom.themes.loadBaseStylesheets() atom.themes.requireStylesheet '../static/jasmine' diff --git a/spec/syntax-spec.coffee b/spec/syntax-spec.coffee index 9e4795d6d..92373c53d 100644 --- a/spec/syntax-spec.coffee +++ b/spec/syntax-spec.coffee @@ -1,7 +1,6 @@ {fs} = require 'atom' path = require 'path' temp = require 'temp' -TextMateGrammar = require '../src/text-mate-grammar' describe "the `syntax` global", -> beforeEach -> @@ -62,20 +61,23 @@ describe "the `syntax` global", -> describe "when multiple grammars have matching fileTypes", -> it "selects the grammar with the longest fileType match", -> - grammar1 = new TextMateGrammar + grammarPath1 = temp.path(suffix: '.json') + fs.writeFileSync grammarPath1, JSON.stringify( name: 'test1' scopeName: 'source1' - fileTypes: ['test', 'more.test'] + fileTypes: ['test'] + ) + grammar1 = atom.syntax.loadGrammarSync(grammarPath1) + expect(atom.syntax.selectGrammar('more.test', '')).toBe grammar1 - grammar2 = new TextMateGrammar + grammarPath2 = temp.path(suffix: '.json') + fs.writeFileSync grammarPath2, JSON.stringify( name: 'test2' scopeName: 'source2' - fileTypes: ['test'] - - atom.syntax.addGrammar(grammar1) - atom.syntax.addGrammar(grammar2) - - expect(atom.syntax.selectGrammar('more.test', '')).toBe grammar1 + fileTypes: ['test', 'more.test'] + ) + grammar2 = atom.syntax.loadGrammarSync(grammarPath2) + expect(atom.syntax.selectGrammar('more.test', '')).toBe grammar2 describe "when there is no file path", -> it "does not throw an exception (regression)", -> diff --git a/spec/text-mate-grammar-spec.coffee b/spec/text-mate-grammar-spec.coffee deleted file mode 100644 index f4984be8e..000000000 --- a/spec/text-mate-grammar-spec.coffee +++ /dev/null @@ -1,704 +0,0 @@ -TextMateGrammar = require '../src/text-mate-grammar' -TextMatePackage = require '../src/text-mate-package' -{_, fs} = require 'atom' - -describe "TextMateGrammar", -> - grammar = null - - beforeEach -> - atom.packages.activatePackage('language-text', sync: true) - atom.packages.activatePackage('language-javascript', sync: true) - atom.packages.activatePackage('language-coffee-script', sync: true) - atom.packages.activatePackage('language-ruby', sync: true) - atom.packages.activatePackage('language-html', sync: true) - atom.packages.activatePackage('language-php', sync: true) - atom.packages.activatePackage('language-python', sync: true) - grammar = atom.syntax.selectGrammar("hello.coffee") - - describe "@loadSync(path)", -> - it "loads grammars from plists", -> - grammar = TextMateGrammar.loadSync(require.resolve('./fixtures/sample.plist')) - expect(grammar.scopeName).toBe "text.plain" - {tokens} = grammar.tokenizeLine("this text is so plain. i love it.") - expect(tokens[0]).toEqual value: "this text is so plain. i love it.", scopes: ["text.plain", "meta.paragraph.text"] - - it "loads grammars from cson files", -> - grammar = TextMateGrammar.loadSync(require.resolve('./fixtures/packages/package-with-grammars/grammars/alot.cson')) - expect(grammar.scopeName).toBe "source.alot" - {tokens} = grammar.tokenizeLine("this is alot of code") - expect(tokens[1]).toEqual value: "alot", scopes: ["source.alot", "keyword.alot"] - - describe ".tokenizeLine(line, ruleStack)", -> - describe "when the entire line matches a single pattern with no capture groups", -> - it "returns a single token with the correct scope", -> - {tokens} = grammar.tokenizeLine("return") - - expect(tokens.length).toBe 1 - [token] = tokens - expect(token.scopes).toEqual ['source.coffee', 'keyword.control.coffee'] - - describe "when the entire line matches a single pattern with capture groups", -> - it "returns a single token with the correct scope", -> - {tokens} = grammar.tokenizeLine("new foo.bar.Baz") - - expect(tokens.length).toBe 3 - [newOperator, whitespace, className] = tokens - expect(newOperator).toEqual value: 'new', scopes: ['source.coffee', 'meta.class.instance.constructor', 'keyword.operator.new.coffee'] - expect(whitespace).toEqual value: ' ', scopes: ['source.coffee', 'meta.class.instance.constructor'] - expect(className).toEqual value: 'foo.bar.Baz', scopes: ['source.coffee', 'meta.class.instance.constructor', 'entity.name.type.instance.coffee'] - - describe "when the line doesn't match any patterns", -> - it "returns the entire line as a single simple token with the grammar's scope", -> - textGrammar = atom.syntax.selectGrammar('foo.txt') - {tokens} = textGrammar.tokenizeLine("abc def") - expect(tokens.length).toBe 1 - - describe "when the line matches multiple patterns", -> - it "returns multiple tokens, filling in regions that don't match patterns with tokens in the grammar's global scope", -> - {tokens} = grammar.tokenizeLine(" return new foo.bar.Baz ") - - expect(tokens.length).toBe 7 - - expect(tokens[0]).toEqual value: ' ', scopes: ['source.coffee'] - expect(tokens[1]).toEqual value: 'return', scopes: ['source.coffee', 'keyword.control.coffee'] - expect(tokens[2]).toEqual value: ' ', scopes: ['source.coffee'] - expect(tokens[3]).toEqual value: 'new', scopes: ['source.coffee', 'meta.class.instance.constructor', 'keyword.operator.new.coffee'] - expect(tokens[4]).toEqual value: ' ', scopes: ['source.coffee', 'meta.class.instance.constructor'] - expect(tokens[5]).toEqual value: 'foo.bar.Baz', scopes: ['source.coffee', 'meta.class.instance.constructor', 'entity.name.type.instance.coffee'] - expect(tokens[6]).toEqual value: ' ', scopes: ['source.coffee'] - - describe "when the line matches a pattern with optional capture groups", -> - it "only returns tokens for capture groups that matched", -> - {tokens} = grammar.tokenizeLine("class Quicksort") - expect(tokens.length).toBe 3 - expect(tokens[0].value).toBe "class" - expect(tokens[1].value).toBe " " - expect(tokens[2].value).toBe "Quicksort" - - describe "when the line matches a rule with nested capture groups and lookahead capture groups beyond the scope of the overall match", -> - it "creates distinct tokens for nested captures and does not return tokens beyond the scope of the overall capture", -> - {tokens} = grammar.tokenizeLine(" destroy: ->") - expect(tokens.length).toBe 6 - expect(tokens[0]).toEqual(value: ' ', scopes: ["source.coffee"]) - expect(tokens[1]).toEqual(value: 'destro', scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee"]) - # this dangling 'y' with a duplicated scope looks wrong, but textmate yields the same behavior. probably a quirk in the coffee grammar. - expect(tokens[2]).toEqual(value: 'y', scopes: ["source.coffee", "meta.function.coffee", "entity.name.function.coffee", "entity.name.function.coffee"]) - expect(tokens[3]).toEqual(value: ':', scopes: ["source.coffee", "keyword.operator.coffee"]) - expect(tokens[4]).toEqual(value: ' ', scopes: ["source.coffee"]) - expect(tokens[5]).toEqual(value: '->', scopes: ["source.coffee", "storage.type.function.coffee"]) - - describe "when the line matches a pattern that includes a rule", -> - it "returns tokens based on the included rule", -> - {tokens} = grammar.tokenizeLine("7777777") - expect(tokens.length).toBe 1 - expect(tokens[0]).toEqual value: '7777777', scopes: ['source.coffee', 'constant.numeric.coffee'] - - describe "when the line is an interpolated string", -> - it "returns the correct tokens", -> - {tokens} = grammar.tokenizeLine('"the value is #{@x} my friend"') - - expect(tokens[0]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: "the value is ", scopes: ["source.coffee","string.quoted.double.coffee"] - expect(tokens[2]).toEqual value: '#{', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[3]).toEqual value: "@x", scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","variable.other.readwrite.instance.coffee"] - expect(tokens[4]).toEqual value: "}", scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[5]).toEqual value: " my friend", scopes: ["source.coffee","string.quoted.double.coffee"] - expect(tokens[6]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","punctuation.definition.string.end.coffee"] - - describe "when the line has an interpolated string inside an interpolated string", -> - it "returns the correct tokens", -> - {tokens} = grammar.tokenizeLine('"#{"#{@x}"}"') - - expect(tokens[0]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","punctuation.definition.string.begin.coffee"] - expect(tokens[1]).toEqual value: '#{', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[2]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","string.quoted.double.coffee","punctuation.definition.string.begin.coffee"] - expect(tokens[3]).toEqual value: '#{', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[4]).toEqual value: '@x', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","string.quoted.double.coffee","source.coffee.embedded.source","variable.other.readwrite.instance.coffee"] - expect(tokens[5]).toEqual value: '}', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[6]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","string.quoted.double.coffee","punctuation.definition.string.end.coffee"] - expect(tokens[7]).toEqual value: '}', scopes: ["source.coffee","string.quoted.double.coffee","source.coffee.embedded.source","punctuation.section.embedded.coffee"] - expect(tokens[8]).toEqual value: '"', scopes: ["source.coffee","string.quoted.double.coffee","punctuation.definition.string.end.coffee"] - - describe "when the line is empty", -> - it "returns a single token which has the global scope", -> - {tokens} = grammar.tokenizeLine('') - expect(tokens[0]).toEqual value: '', scopes: ["source.coffee"] - - describe "when the line matches no patterns", -> - it "does not infinitely loop", -> - grammar = atom.syntax.selectGrammar("sample.txt") - {tokens} = grammar.tokenizeLine('hoo') - expect(tokens.length).toBe 1 - expect(tokens[0]).toEqual value: 'hoo', scopes: ["text.plain", "meta.paragraph.text"] - - describe "when the line matches a pattern with a 'contentName'", -> - it "creates tokens using the content of contentName as the token name", -> - grammar = atom.syntax.selectGrammar("sample.txt") - {tokens} = grammar.tokenizeLine('ok, cool') - expect(tokens[0]).toEqual value: 'ok, cool', scopes: ["text.plain", "meta.paragraph.text"] - - describe "when the line matches a pattern with no `name` or `contentName`", -> - it "creates tokens without adding a new scope", -> - grammar = atom.syntax.selectGrammar('foo.rb') - {tokens} = grammar.tokenizeLine('%w|oh \\look|') - expect(tokens.length).toBe 5 - expect(tokens[0]).toEqual value: '%w|', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby", "punctuation.definition.string.begin.ruby"] - expect(tokens[1]).toEqual value: 'oh ', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby"] - expect(tokens[2]).toEqual value: '\\l', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby"] - expect(tokens[3]).toEqual value: 'ook', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby"] - - describe "when the line matches a begin/end pattern", -> - it "returns tokens based on the beginCaptures, endCaptures and the child scope", -> - {tokens} = grammar.tokenizeLine("'''single-quoted heredoc'''") - - expect(tokens.length).toBe 3 - - expect(tokens[0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: "single-quoted heredoc", scopes: ['source.coffee', 'string.quoted.heredoc.coffee'] - expect(tokens[2]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - describe "when the pattern spans multiple lines", -> - it "uses the ruleStack returned by the first line to parse the second line", -> - {tokens: firstTokens, ruleStack} = grammar.tokenizeLine("'''single-quoted") - {tokens: secondTokens, ruleStack} = grammar.tokenizeLine("heredoc'''", ruleStack) - - expect(firstTokens.length).toBe 2 - expect(secondTokens.length).toBe 2 - - expect(firstTokens[0]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(firstTokens[1]).toEqual value: "single-quoted", scopes: ['source.coffee', 'string.quoted.heredoc.coffee'] - - expect(secondTokens[0]).toEqual value: "heredoc", scopes: ['source.coffee', 'string.quoted.heredoc.coffee'] - expect(secondTokens[1]).toEqual value: "'''", scopes: ['source.coffee', 'string.quoted.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - describe "when the pattern contains sub-patterns", -> - it "returns tokens within the begin/end scope based on the sub-patterns", -> - {tokens} = grammar.tokenizeLine('"""heredoc with character escape \\t"""') - - expect(tokens.length).toBe 4 - - expect(tokens[0]).toEqual value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.begin.coffee'] - expect(tokens[1]).toEqual value: "heredoc with character escape ", scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee'] - expect(tokens[2]).toEqual value: "\\t", scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'constant.character.escape.coffee'] - expect(tokens[3]).toEqual value: '"""', scopes: ['source.coffee', 'string.quoted.double.heredoc.coffee', 'punctuation.definition.string.end.coffee'] - - describe "when the end pattern contains a back reference", -> - it "constructs the end rule based on its back-references to captures in the begin rule", -> - grammar = atom.syntax.selectGrammar('foo.rb') - {tokens} = grammar.tokenizeLine('%w|oh|,') - expect(tokens.length).toBe 4 - expect(tokens[0]).toEqual value: '%w|', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby", "punctuation.definition.string.begin.ruby"] - expect(tokens[1]).toEqual value: 'oh', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby"] - expect(tokens[2]).toEqual value: '|', scopes: ["source.ruby", "string.quoted.other.literal.lower.ruby", "punctuation.definition.string.end.ruby"] - expect(tokens[3]).toEqual value: ',', scopes: ["source.ruby", "punctuation.separator.object.ruby"] - - it "allows the rule containing that end pattern to be pushed to the stack multiple times", -> - grammar = atom.syntax.selectGrammar('foo.rb') - {tokens} = grammar.tokenizeLine('%Q+matz had some #{%Q-crazy ideas-} for ruby syntax+ # damn.') - expect(tokens[0]).toEqual value: '%Q+', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","punctuation.definition.string.begin.ruby"] - expect(tokens[1]).toEqual value: 'matz had some ', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby"] - expect(tokens[2]).toEqual value: '#{', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","meta.embedded.line.ruby","punctuation.section.embedded.begin.ruby"] - expect(tokens[3]).toEqual value: '%Q-', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","meta.embedded.line.ruby","string.quoted.other.literal.upper.ruby","punctuation.definition.string.begin.ruby"] - expect(tokens[4]).toEqual value: 'crazy ideas', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","meta.embedded.line.ruby","string.quoted.other.literal.upper.ruby"] - expect(tokens[5]).toEqual value: '-', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","meta.embedded.line.ruby","string.quoted.other.literal.upper.ruby","punctuation.definition.string.end.ruby"] - expect(tokens[6]).toEqual value: '}', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","meta.embedded.line.ruby","punctuation.section.embedded.end.ruby", "source.ruby"] - expect(tokens[7]).toEqual value: ' for ruby syntax', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby"] - expect(tokens[8]).toEqual value: '+', scopes: ["source.ruby","string.quoted.other.literal.upper.ruby","punctuation.definition.string.end.ruby"] - expect(tokens[9]).toEqual value: ' ', scopes: ["source.ruby"] - expect(tokens[10]).toEqual value: '#', scopes: ["source.ruby","comment.line.number-sign.ruby","punctuation.definition.comment.ruby"] - expect(tokens[11]).toEqual value: ' damn.', scopes: ["source.ruby","comment.line.number-sign.ruby"] - - describe "when the pattern includes rules from another grammar", -> - describe "when a grammar matching the desired scope is available", -> - it "parses tokens inside the begin/end patterns based on the included grammar's rules", -> - atom.packages.activatePackage('language-html', sync: true) - atom.packages.activatePackage('language-ruby-on-rails', sync: true) - - grammar = atom.syntax.grammarForScopeName('text.html.ruby') - {tokens} = grammar.tokenizeLine("