file_glob 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +35 -0
- data/Rakefile +9 -0
- data/lib/file_glob.rb +71 -0
- data/test/file_glob_interface_test.rb +18 -0
- data/test/file_glob_test.rb +38 -0
- data/test/matcher_mixin.rb +36 -0
- data/test/regexp_interface_test.rb +19 -0
- metadata +53 -0
data/README.markdown
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
FileGlob
|
2
|
+
========
|
3
|
+
|
4
|
+
Quacks like a Regexp, tastes like Dir.glob.
|
5
|
+
|
6
|
+
Use this with any library that expects a regular expression. Use FileGlob in place of a Regexp when [shell pattern matching ](http://www.ruby-doc.org/core-1.9.3/File.html#method-c-fnmatch) makes more sense.
|
7
|
+
|
8
|
+
Usage
|
9
|
+
-----
|
10
|
+
|
11
|
+
Filter a set of file paths:
|
12
|
+
|
13
|
+
glob = FileGlob.new("test/**/*_test.rb")
|
14
|
+
paths.select{|path| path =~ glob }
|
15
|
+
|
16
|
+
Perform different actions for different file types:
|
17
|
+
|
18
|
+
image = FileGlob.new("*.{png,jpg,gif}")
|
19
|
+
text = FileGlob.new("*.txt")
|
20
|
+
|
21
|
+
case path
|
22
|
+
when image then process_image(path)
|
23
|
+
when text then process_text(path)
|
24
|
+
end
|
25
|
+
|
26
|
+
Installation
|
27
|
+
------------
|
28
|
+
|
29
|
+
Install with rubygems:
|
30
|
+
|
31
|
+
gem install file_glob
|
32
|
+
|
33
|
+
-----
|
34
|
+
|
35
|
+
Adam Sanderson, http://www.monkeyandcrow.com
|
data/Rakefile
ADDED
data/lib/file_glob.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
class FileGlob
|
2
|
+
attr_reader :pattern
|
3
|
+
|
4
|
+
def initialize(pattern)
|
5
|
+
@pattern = pattern
|
6
|
+
end
|
7
|
+
|
8
|
+
def =~ path
|
9
|
+
0 if File.fnmatch?(pattern, path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def === path
|
13
|
+
File.fnmatch?(pattern, path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def match(path)
|
17
|
+
GlobMatchData.new(path) if self =~ path
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
pattern
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
"<#FileGlob #{pattern}>"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Interface that quacks like Regexp's MatchData.
|
31
|
+
# It should cover most common cases.
|
32
|
+
class GlobMatchData
|
33
|
+
attr_reader :string
|
34
|
+
|
35
|
+
def intialize(string)
|
36
|
+
@string = string
|
37
|
+
end
|
38
|
+
|
39
|
+
def [] i
|
40
|
+
check_index!(i)
|
41
|
+
string
|
42
|
+
end
|
43
|
+
|
44
|
+
def begin(i)
|
45
|
+
check_index!(i)
|
46
|
+
0
|
47
|
+
end
|
48
|
+
|
49
|
+
def end
|
50
|
+
check_index!(i)
|
51
|
+
string.length
|
52
|
+
end
|
53
|
+
|
54
|
+
def size
|
55
|
+
1
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :length, :size
|
59
|
+
|
60
|
+
def names
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def check_index!(i)
|
67
|
+
throw IndexError.new("FileGlob only matches once") if i > 0
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "./matcher_mixin"
|
3
|
+
require_relative "../lib/file_glob"
|
4
|
+
|
5
|
+
# Ensure our interface matches the "matcher" duck type of Regexp.
|
6
|
+
#
|
7
|
+
class FileGlobInterfaceTest < MiniTest::Unit::TestCase
|
8
|
+
include MatcherMixin
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@matcher = FileGlob.new("*.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
def matching_example
|
15
|
+
"file.rb"
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "../lib/file_glob"
|
3
|
+
|
4
|
+
class FileGlobTest < MiniTest::Unit::TestCase
|
5
|
+
MATCH = "file.rb"
|
6
|
+
NO_MATCH = "file.yml"
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@glob = FileGlob.new '*.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_matches_with_squiggle_operator
|
13
|
+
assert @glob =~ MATCH
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_only_matches_when_pattern_matches
|
17
|
+
assert !(@glob =~ NO_MATCH)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_can_be_used_on_righthand_side
|
21
|
+
assert MATCH =~ @glob
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_matches_with_match
|
25
|
+
assert @glob.match(MATCH)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_only_matches_with_match_when_pattern_matches
|
29
|
+
assert !@glob.match(NO_MATCH)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_can_be_used_in_a_case_statement
|
33
|
+
case MATCH
|
34
|
+
when @glob then assert(true)
|
35
|
+
else flunk "Should define ==="
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# These tests minimaly verify the interface of a "matcher" object.
|
2
|
+
# They ensure that it behaves like a regexp for matching purposes.
|
3
|
+
#
|
4
|
+
# For tests around behavior, see file_glob_test.rb
|
5
|
+
#
|
6
|
+
module MatcherMixin
|
7
|
+
|
8
|
+
def setup
|
9
|
+
raise NotImplementedError.new "Setup must define @matcher"
|
10
|
+
end
|
11
|
+
|
12
|
+
def matching_example
|
13
|
+
raise NotImplementedError.new "Provide a string that matches @matcher"
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_responds_to_matching_methods
|
17
|
+
assert @matcher.respond_to? :"=~"
|
18
|
+
assert @matcher.respond_to? :match
|
19
|
+
assert @matcher.respond_to? :"==="
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_squiggle_operator_returns_an_index
|
23
|
+
i = @matcher =~ matching_example
|
24
|
+
|
25
|
+
assert_kind_of Fixnum, i
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_match_returns_a_match_data_like_object
|
29
|
+
data = @matcher.match(matching_example)
|
30
|
+
|
31
|
+
assert data.respond_to? :[]
|
32
|
+
assert data.respond_to? :string
|
33
|
+
assert data.respond_to? :length
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "minitest/autorun"
|
2
|
+
require_relative "./matcher_mixin"
|
3
|
+
|
4
|
+
# Verify that Regexp quacks like a "matcher".
|
5
|
+
#
|
6
|
+
# This might seem silly, but it ensures that the duck type we are attempting to
|
7
|
+
# match actually matches our expectations.
|
8
|
+
#
|
9
|
+
class RegexpInterfaceTest < MiniTest::Unit::TestCase
|
10
|
+
include MatcherMixin
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@matcher = /.+\.rb/
|
14
|
+
end
|
15
|
+
|
16
|
+
def matching_example
|
17
|
+
"file.rb"
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: file_glob
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Sanderson
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-15 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Use FileGlob in place of a Regexp when shell pattern matching makes more
|
15
|
+
sense.
|
16
|
+
email:
|
17
|
+
- netghost@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/file_glob.rb
|
23
|
+
- test/file_glob_interface_test.rb
|
24
|
+
- test/file_glob_test.rb
|
25
|
+
- test/matcher_mixin.rb
|
26
|
+
- test/regexp_interface_test.rb
|
27
|
+
- README.markdown
|
28
|
+
- Rakefile
|
29
|
+
homepage: https://github.com/adamsanderson/file_glob
|
30
|
+
licenses: []
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 1.8.11
|
50
|
+
signing_key:
|
51
|
+
specification_version: 3
|
52
|
+
summary: Quacks like a Regexp, tastes like your shell's a file glob.
|
53
|
+
test_files: []
|