Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit cb07bf0

Browse files
committed
Change settings to use bash-like globbing
1 parent ca8e809 commit cb07bf0

File tree

5 files changed

+50
-120
lines changed

5 files changed

+50
-120
lines changed

lib/matcher.coffee

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,18 @@
1-
# See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
2-
escapeRegExp = (string) ->
3-
# $& means the whole matched string
4-
string.replace /[.*+?^${}()|[\]\\]/g, '\\$&'
1+
{Minimatch} = require 'minimatch'
52

63
module.exports =
74
class Matcher
8-
constructor: (matcher, scopeName, opts = {}) ->
9-
regexpOpts = ''
10-
11-
if opts.caseSensitive
12-
regexpOpts += 'i'
13-
14-
matcher = if matcher? then "#{matcher}" else ''
15-
16-
if matcher.length <= 0
17-
# TODO: Throw error?
18-
@_regexp = null
19-
else if /(^\^)|([.|])|(\$$)/.test matcher
20-
@_regexp = new RegExp "(#{matcher})", regexpOpts
21-
else
22-
# Otherwise, we assume it is an extension matcher
23-
@_regexp = new RegExp "(\\.#{escapeRegExp(matcher)}$)", regexpOpts
5+
constructor: (pattern, scopeName, opts = {}) ->
6+
@_matcher = new Minimatch pattern,
7+
matchBase: true
8+
nobrace: true
9+
nocomment: true
10+
nocase: !!opts.caseSensitive
11+
noext: true
12+
nonegate: true
2413

2514
match: (string) ->
26-
RegExp.lastMatch if @_regexp?.test(string)
15+
@_matcher.match string
2716

2817
toString: ->
29-
if @_regexp? then @_regexp.toString() else 'undefined'
18+
@_matcher.pattern

lib/scope-name-provider.coffee

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ class ScopeNameProvider
77
@_matchers = {}
88
@_scopeNames = {}
99

10-
registerMatcher: (matcher, scopeName, opts = {}) ->
10+
registerMatcher: (pattern, scopeName, opts = {}) ->
1111
@_matchers[scopeName] ?= []
12-
matcher = new Matcher matcher, scopeName, opts
12+
matcher = new Matcher pattern, scopeName, opts
1313
@_matchers[scopeName].push matcher
1414
@_scopeNames[scopeName] = scopeName
1515
return # void
1616

1717
getScopeName: (filename) ->
18-
# scopeName : {match, matcher}
18+
# scopeName : pattern
1919
matches = @_matchFilename filename
2020
keys = Object.keys matches
2121
len = keys.length
@@ -30,8 +30,8 @@ class ScopeNameProvider
3030

3131
# Sort keys by match alphabetically
3232
keys.sort (a, b) ->
33-
a = matches[a].match
34-
b = matches[b].match
33+
a = matches[a]
34+
b = matches[b]
3535
if a < b
3636
-1
3737
else if a > b
@@ -44,7 +44,11 @@ class ScopeNameProvider
4444

4545
# Show a notification
4646
atom.notifications.addWarning '[file-types] Multiple Matches',
47-
detail: "Assuming '#{scopeName}' for file '#{filename}'.\n\n#{("- '#{m.matcher}': '#{sn}' matched '#{m.match}'" for sn, m of matches).join '\n'}"
47+
detail: """
48+
Assuming '#{scopeName}' for file '#{filename}'.
49+
50+
#{("- '#{p}': '#{sn}'" for sn, p of matches).join '\n'}
51+
"""
4852
dismissable: true
4953

5054
return scopeName
@@ -64,11 +68,11 @@ class ScopeNameProvider
6468
# Start with previously longest length found and no match
6569
longestLengthForScope = longestLength
6670
longestMatchForScope = null
67-
longestMatcherForScope = null
6871

6972
for matcher in matchers
70-
continue unless (match = matcher.match(filename))?
73+
continue unless matcher.match(filename)
7174

75+
match = matcher.toString()
7276
len = match.length
7377

7478
# Just skip if less-than longest length for scope
@@ -77,19 +81,16 @@ class ScopeNameProvider
7781
# Save match if longest (or equal-to longest) for scope
7882
longestLengthForScope = len
7983
longestMatchForScope = match
80-
longestMatcherForScope = matcher
8184

8285
# Skip this scope if no matches found
83-
continue unless longestMatcherForScope?
86+
continue unless longestMatchForScope?
8487

8588
# Reset longest matches if longest
8689
if longestLengthForScope > longestLength
8790
longestMatches = {}
8891

8992
# Save the longest match info
9093
longestLength = longestLengthForScope
91-
longestMatches[scopeName] =
92-
match: longestMatchForScope
93-
matcher: longestMatcherForScope.toString()
94+
longestMatches[scopeName] = longestMatchForScope
9495

9596
longestMatches

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"description": "Specify additional file types for languages.",
66
"repository": "https://github.com/execjosh/atom-file-types",
77
"license": "MIT",
8+
"dependencies": {
9+
"minimatch": "^3.0.2"
10+
},
811
"engines": {
912
"atom": ">=0.185.0 <2.0.0"
1013
}

spec/matcher-spec.coffee

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,4 @@
11
Matcher = require '../lib/matcher'
22

33
describe 'Matcher', ->
4-
describe 'constructor', ->
5-
it 'creates null regexp for null input', ->
6-
matcher = new Matcher null
7-
expect(matcher._regexp).toBe null
8-
9-
it 'creates null regexp for empty input', ->
10-
matcher = new Matcher ''
11-
expect(matcher._regexp).toBe null
12-
13-
describe 'with carat (^)', ->
14-
it 'creates regexp for input starting with a carat (^)', ->
15-
matcher = new Matcher '^rb'
16-
expect(matcher._regexp.toString()).toBe "/(^rb)/"
17-
18-
it 'creates "extension" regexp for input containing, but not starting, with a carat (^)', ->
19-
matcher = new Matcher 'r^b'
20-
expect(matcher._regexp.toString()).toBe '/(\\.r\\^b$)/'
21-
22-
it 'creates "extension" regexp for input ending, but not starting, with a carat (^)', ->
23-
matcher = new Matcher 'r^'
24-
expect(matcher._regexp.toString()).toBe '/(\\.r\\^$)/'
25-
26-
describe 'with dollar ($)', ->
27-
it 'creates regexp for input ending with a dollar ($)', ->
28-
matcher = new Matcher 'rb$'
29-
expect(matcher._regexp.toString()).toBe "/(rb$)/"
30-
31-
it 'creates "extension" regexp for input containing, but not ending, with a dollar ($)', ->
32-
matcher = new Matcher 'r$b'
33-
expect(matcher._regexp.toString()).toBe '/(\\.r\\$b$)/'
34-
35-
it 'creates "extension" regexp for input starting, but not ending, with a dollar ($)', ->
36-
matcher = new Matcher '$b'
37-
expect(matcher._regexp.toString()).toBe '/(\\.\\$b$)/'
38-
39-
describe 'with unescaped dot (.)', ->
40-
it 'creates regexp for input starting with a dot (.)', ->
41-
matcher = new Matcher '.rb'
42-
expect(matcher._regexp.toString()).toBe "/(.rb)/"
43-
44-
it 'creates regexp for input containing, but neither starting nor ending, with a dot (.)', ->
45-
matcher = new Matcher 'r.b'
46-
expect(matcher._regexp.toString()).toBe '/(r.b)/'
47-
48-
it 'creates regexp for input ending with a dot (.)', ->
49-
matcher = new Matcher 'rb.'
50-
expect(matcher._regexp.toString()).toBe "/(rb.)/"
51-
52-
describe 'with escaped dot (.)', ->
53-
it 'creates regexp for input starting with an escaped dot (.)', ->
54-
matcher = new Matcher '\\.rb'
55-
expect(matcher._regexp.toString()).toBe "/(\\.rb)/"
56-
57-
it 'creates regexp for input containing, but neither starting nor ending, with an escaped dot (.)', ->
58-
matcher = new Matcher 'r\\.b'
59-
expect(matcher._regexp.toString()).toBe '/(r\\.b)/'
60-
61-
it 'creates regexp for input ending with an escaped dot (.)', ->
62-
matcher = new Matcher 'rb\\.'
63-
expect(matcher._regexp.toString()).toBe "/(rb\\.)/"
64-
65-
describe 'with pipe (|)', ->
66-
it 'creates regexp for input containing, but neither starting nor ending, with a pipe (|)', ->
67-
matcher = new Matcher 'r|b'
68-
expect(matcher._regexp.toString()).toBe '/(r|b)/'
4+
xdescribe 'constructor', ->

spec/scope-name-provider-spec.coffee

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,45 @@ describe 'ScopeNameProvider', ->
1010

1111
describe 'scope provision', ->
1212
it 'provides scope name based on file extension', ->
13-
snp.registerMatcher 'blah', 'text.plain.test-grammar'
13+
snp.registerMatcher '*.blah', 'text.plain.test-grammar'
1414
expect(snp.getScopeName 'hogehoge.blah').toBe 'text.plain.test-grammar'
1515

1616
it 'provides scope name based on regexp matcher', ->
17-
snp.registerMatcher 'spec\\.coffee$', 'test.coffee.spec'
17+
snp.registerMatcher '*spec.coffee', 'test.coffee.spec'
1818
expect(snp.getScopeName 'super-human-spec.coffee').toBe 'test.coffee.spec'
1919

2020
it 'gives precedence to longest match', ->
21-
snp.registerMatcher 'blah', 'text.plain.test-grammar'
22-
snp.registerMatcher 'spec\\.blah$', 'test.blah.spec'
23-
expect(snp.getScopeName 'super-human-spec.blah').toBe 'test.blah.spec'
24-
25-
it 'gives precedence to last match for match length tie-breaker', ->
26-
snp.registerMatcher 'rb', 'text.plain.test-grammar'
27-
snp.registerMatcher '\\.r(a|b)$', 'test.blah.spec'
28-
expect(snp.getScopeName 'super-human-spec.rb').toBe 'test.blah.spec'
21+
matchers =
22+
'*.css.liquid': 'source.css'
23+
'*.scss.liquid': 'source.css.scss'
24+
'*.liquid': 'text.html.basic'
25+
'*_spec.rb': 'source.ruby.rspec'
26+
'*.rb': 'source.ruby'
27+
for pattern, scopeName of matchers
28+
snp.registerMatcher pattern, scopeName
29+
expect(snp.getScopeName 'some_controller_spec.rb').toBe 'source.ruby.rspec'
30+
expect(snp.getScopeName 'some_controller.rb').toBe 'source.ruby'
31+
expect(snp.getScopeName 'something.liquid').toBe 'text.html.basic'
32+
expect(snp.getScopeName 'something.scss.liquid').toBe 'source.css.scss'
33+
expect(snp.getScopeName 'something.css.liquid').toBe 'source.css'
2934

30-
describe 'regexp matcher', ->
35+
describe 'globbing matcher', ->
3136
it 'can match start-of-string', ->
32-
snp.registerMatcher '^spec', 'test.spec'
37+
snp.registerMatcher 'spec*', 'test.spec'
3338
expect(snp.getScopeName 'spec-super-human.coffee').toBe 'test.spec'
3439
expect(snp.getScopeName 'super-human-spec.coffee').toEqualNull()
3540

3641
it 'can match mid-string', ->
37-
snp.registerMatcher 'sp.c', 'test.spec'
42+
snp.registerMatcher 'sp*.coffee', 'test.spec'
3843
expect(snp.getScopeName 'spec-super-human.coffee').toBe 'test.spec'
39-
expect(snp.getScopeName 'super-human-spec.coffee').toBe 'test.spec'
40-
expect(snp.getScopeName 'super-human-spock.coffee').toBe 'test.spec'
44+
expect(snp.getScopeName 'super-human-spec.coffee').toEqualNull()
45+
expect(snp.getScopeName 'super-human-spock.coffee').toEqualNull()
4146

4247
it 'can match end-of-string', ->
43-
snp.registerMatcher 'spec$', 'test.spec'
48+
snp.registerMatcher '*spec', 'test.spec'
4449
expect(snp.getScopeName 'spec-super-human').toEqualNull()
4550
expect(snp.getScopeName 'super-human-spec').toBe 'test.spec'
4651

47-
it 'can match escaped dots', ->
48-
snp.registerMatcher '_spec\\.rb$', 'source.ruby.rspec'
49-
expect(snp.getScopeName 'really_cool_controller_spec.rb').toBe 'source.ruby.rspec'
50-
5152
describe 'registered scope name list provision', ->
5253
it 'initially has no scope names', ->
5354
expect(snp.getScopeNames()).toEqual []

0 commit comments

Comments
 (0)