From 86c83431074dbc9b8aaea04b8d31c9ca00e26f1d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Jun 2013 18:23:54 -0700 Subject: [PATCH] Score grammar matches using longest fileType match Previously the score for two grammars matching on path was equal and so the first one would be selected. Now the longer match will have a higher score and will be selected over other grammars with shorter fileType match lengths. Closes #602 --- spec/app/syntax-spec.coffee | 18 ++++++++++++++++++ src/app/text-mate-grammar.coffee | 22 +++++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/spec/app/syntax-spec.coffee b/spec/app/syntax-spec.coffee index 50917c30c..497bb88ff 100644 --- a/spec/app/syntax-spec.coffee +++ b/spec/app/syntax-spec.coffee @@ -1,4 +1,5 @@ fsUtils = require 'fs-utils' +TextMateGrammar = require 'text-mate-grammar' describe "the `syntax` global", -> beforeEach -> @@ -57,6 +58,23 @@ describe "the `syntax` global", -> syntax.clearGrammarOverrideForPath(path) expect(syntax.selectGrammar(path).name).not.toBe 'Ruby' + describe "when multiple grammars have matching fileTypes", -> + it "selects the grammar with the longest fileType match", -> + grammar1 = new TextMateGrammar + name: 'test1' + scopeName: 'source1' + fileTypes: ['test', 'more.test'] + + grammar2 = new TextMateGrammar + name: 'test2' + scopeName: 'source2' + fileTypes: ['test'] + + syntax.addGrammar(grammar1) + syntax.addGrammar(grammar2) + + expect(syntax.selectGrammar('more.test', '')).toBe grammar1 + describe ".removeGrammar(grammar)", -> it "removes the grammar, so it won't be returned by selectGrammar", -> grammar = syntax.selectGrammar('foo.js') diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index f86435026..5796631b0 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -74,14 +74,13 @@ class TextMateGrammar getScore: (filePath, contents) -> contents = fsUtils.read(filePath) if not contents? and fsUtils.isFileSync(filePath) + if syntax.grammarOverrideForPath(filePath) is @scopeName - 3 + 2 + filePath.length else if @matchesContents(contents) - 2 - else if @matchesPath(filePath) - 1 + 1 + filePath.length else - -1 + @getPathScore(filePath) matchesContents: (contents) -> return false unless contents? and @firstLineRegex? @@ -100,13 +99,18 @@ class TextMateGrammar lines = contents.split('\n') @firstLineRegex.test(lines[0..numberOfNewlinesInRegex].join('\n')) - matchesPath: (filePath) -> - return false unless filePath? + getPathScore: (filePath) -> + return -1 unless filePath? + pathComponents = filePath.split(pathSplitRegex) - _.find @fileTypes, (fileType) -> + pathScore = -1 + @fileTypes.forEach (fileType) -> fileTypeComponents = fileType.split(pathSplitRegex) pathSuffix = pathComponents[-fileTypeComponents.length..-1] - _.isEqual(pathSuffix, fileTypeComponents) + if _.isEqual(pathSuffix, fileTypeComponents) + pathScore = Math.max(pathScore, fileType.length) + + pathScore tokenizeLine: (line, ruleStack=[@getInitialRule()], firstLine=false) -> originalRuleStack = ruleStack