diff --git a/spec/app/text-mate-grammar-spec.coffee b/spec/app/text-mate-grammar-spec.coffee index eb4239e80..d98d6ca06 100644 --- a/spec/app/text-mate-grammar-spec.coffee +++ b/spec/app/text-mate-grammar-spec.coffee @@ -488,6 +488,29 @@ describe "TextMateGrammar", -> expect(tokens[2].value).toBe "SELECT" expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"] + describe "when the position doesn't advance and rule includes $self and matches itself", -> + it "token the entire line using the rule", -> + grammar = new TextMateGrammar + name: "test" + scopeName: "source" + repository: {} + patterns: [ + { + name: "text" + begin: "(?=forever)" + end: "whatevs" + patterns: [ + include: "$self" + ] + } + ] + + {tokens} = grammar.tokenizeLine("forever and ever") + + expect(tokens.length).toBe 1 + expect(tokens[0].value).toBe "forever and ever" + expect(tokens[0].scopes).toEqual ["source", "text"] + describe "language-specific integration tests", -> lines = null diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index b600147a7..cf48323c0 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -155,9 +155,19 @@ class TextMateGrammar )) break - if position == previousPosition and ruleStack.length == previousRuleStackLength - console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack)) - ruleStack.pop() + if position == previousPosition + if ruleStack.length == previousRuleStackLength + console.error("Popping rule because it loops at column #{position} of line '#{line}'", _.clone(ruleStack)) + ruleStack.pop() + + [penultimateRule, lastRule] = ruleStack[-2..] + if lastRule? and penultimateRule.scopeName == lastRule.scopeName + ruleStack.pop() + tokens.push(new Token( + value: line[position...line.length] + scopes: scopes + )) + break ruleStack.forEach (rule) -> rule.clearAnchorPosition() { tokens, ruleStack }