joker 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.
@@ -0,0 +1,6 @@
1
+ # 0.0.1 #
2
+
3
+ * Initial release
4
+ * Ability to match Wildcards against strings
5
+ * Ability to quote strings for use in Wildcards
6
+
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2009 Fabian Streitel
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
@@ -0,0 +1,70 @@
1
+ # Joker #
2
+
3
+ <http://karottenreibe.github.com/joker>
4
+
5
+ Joker is a simple Wildcard (a.k.a Glob Pattern) implementition
6
+ for Ruby.
7
+
8
+ ## Features ##
9
+
10
+ * Behaves much like Regexp
11
+ * ` * ` and ` ? ` as wildcard characters
12
+ * ` \ ` for escaping
13
+ * `\a` matches `\a`, but not `a`
14
+ * Wildcards must always match whole string
15
+ * Wildcards can be case insensitive
16
+
17
+ ## Installation ##
18
+
19
+ gem install karottenreibe-joker --source http://gems.github.com
20
+ gem install joker
21
+
22
+ ## Usage ##
23
+
24
+ require 'rubygems'
25
+ require 'joker'
26
+
27
+
28
+ wild = Wildcard['Fairy?ake*']
29
+
30
+ wild =~ 'Fairycake' #=> true
31
+ wild =~ 'Fairyfakes' #=> true
32
+ wild =~ 'Fairylake is a cool place' #=> true
33
+
34
+ wild =~ 'Dairycake' #=> false
35
+ wild =~ 'Fairysteakes' #=> false
36
+ wild =~ 'fairycake' #=> false
37
+
38
+ wildi = Wildcard['Fairy?ake*\?', true]
39
+
40
+ wildi =~ 'FairyCake?' #=> true
41
+ wildi =~ 'fairyfakes?' #=> true
42
+ wildi =~ 'FairyLake IS A COOL Place?' #=> true
43
+
44
+ Wildcard.quote('*?\\') #=> '\\*\\?\\\\'
45
+
46
+ ## License ##
47
+
48
+ Copyright (c) 2009 Fabian Streitel
49
+
50
+ Permission is hereby granted, free of charge, to any person
51
+ obtaining a copy of this software and associated documentation
52
+ files (the "Software"), to deal in the Software without
53
+ restriction, including without limitation the rights to use,
54
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
55
+ copies of the Software, and to permit persons to whom the
56
+ Software is furnished to do so, subject to the following
57
+ conditions:
58
+
59
+ The above copyright notice and this permission notice shall be
60
+ included in all copies or substantial portions of the Software.
61
+
62
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
63
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
64
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
65
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
66
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
67
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
68
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
69
+ OTHER DEALINGS IN THE SOFTWARE.
70
+
@@ -0,0 +1,20 @@
1
+ require 'jeweler'
2
+
3
+ task :build => :gemspec
4
+
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = 'joker'
7
+ gem.summary = gem.description =
8
+ 'Joker is a simple wildcard implementation that works much like Regexps'
9
+ gem.email = 'karottenreibe@gmail.com'
10
+ gem.homepage = 'http://karottenreibe.github.com/joker'
11
+ gem.authors = ['Fabian Streitel']
12
+ gem.rubyforge_project = 'k-gems'
13
+ end
14
+
15
+ Jeweler::RubyforgeTasks.new
16
+
17
+ task :test do
18
+ sh 'bacon -Ilib test/test_*.rb'
19
+ end
20
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,179 @@
1
+ #
2
+ # Joker is a simple Wildcard implementation that works much like Regexps.
3
+ #
4
+
5
+ #
6
+ # Implements wildcards for Ruby. Modeled after the Regexp class.
7
+ #
8
+ # This implementation supports the following special characters:
9
+ #
10
+ # - ? matches a single character
11
+ # - * matches any number of characters, including 0
12
+ # - \\* matches a literal '*'
13
+ # - \\? matches a literal '?'
14
+ # - \\\\ matches a literal '\\'
15
+ # - [xyz] matches either 'x', 'y' or 'z'. NOTE that you have
16
+ # to escape ']' in these groups: \\]
17
+ #
18
+ # NOTE that '\\a' will match the literal string '\\a', not 'a' as
19
+ # one might expect.
20
+ #
21
+ # wild = Wildcard['Fairy?ake*']
22
+ # wild =~ 'Fairycake' #=> true
23
+ # wild =~ 'Fairyfakes are mean' #=> true
24
+ # wild =~ 'Fairysteakes are delicious' #=> false
25
+ #
26
+ # Also there is a case sensitivity flag. By default it is set to true,
27
+ # but it can be turned off at construction time:
28
+ #
29
+ # wild = Wildcard['Fairy?ake*', true]
30
+ # wild =~ 'Fairycake'
31
+ # wild =~ 'fairyCAKE'
32
+ # wild =~ 'FaIrYfAkEs, the Movie'
33
+ #
34
+ # Furthermore, any given Wildcard expression must match the whole string:
35
+ #
36
+ # wild = Wildcard['Fairy?ake']
37
+ # wild =~ 'some Fairycake' #=> false
38
+ # wild =~ 'Fairycake is good for you' #=> false
39
+ #
40
+ class Wildcard
41
+
42
+ #
43
+ # Boolean. Determines case sensitivity of the Wildcard.
44
+ #
45
+ # If this is true, the Wildcard will ignore case.
46
+ #
47
+ attr_reader :casefold
48
+
49
+ #
50
+ # The string from which the Wildcard was constructed.
51
+ #
52
+ attr_reader :source
53
+
54
+ #
55
+ # Creates a new Wildcard from the given string.
56
+ # If casefold is true, the Wildcard will ignore case.
57
+ #
58
+ def initialize( wildcard_string, casefold = false )
59
+ @source = wildcard_string
60
+ @casefold = casefold
61
+ @regexp =
62
+ if casefold then Regexp.new(compile, Regexp::IGNORECASE)
63
+ else Regexp.new(compile)
64
+ end
65
+ end
66
+
67
+ class << self
68
+
69
+ #
70
+ # Returns a new string with any characters escaped that would have
71
+ # special meaning in a Wildcard.
72
+ #
73
+ def quote( string )
74
+ string.gsub(%r{[\\?*\[]}) { |char| "\\#{char}" }
75
+ end
76
+
77
+ alias_method :[], :new
78
+ alias_method :compile, :new
79
+ alias_method :escape, :quote
80
+
81
+ end
82
+
83
+ def inspect
84
+ %{Wildcard[#{@source.inspect}]#{@casefold ? 'i' : ''}}
85
+ end
86
+
87
+ #
88
+ # Matches the wildcard against $_:
89
+ #
90
+ # $_ = 'I love fairycakes'
91
+ # ~Wildcard['*fairy*'] #=> true
92
+ #
93
+ def ~
94
+ self =~ $_
95
+ end
96
+
97
+ #
98
+ # Matches the Wildcard against the given string.
99
+ #
100
+ # NOTE: Since a wildcard has to match the whole string,
101
+ # this method only returns true or false, not the position
102
+ # of the match.
103
+ #
104
+ # Wildcard['*fairy*'] =~ 'I love fairycake' #=> true
105
+ # 'I love fairycake' =~ Wildcard['*dairy*'] #=> false
106
+ #
107
+ def =~( string )
108
+ !!(@regexp =~ string)
109
+ end
110
+
111
+ #
112
+ # The case operator. Allows you to use Wildcards in case
113
+ # expressions:
114
+ #
115
+ # case 'I love fairycake'
116
+ # when Wildcard['*fairy*'] then puts 'fairy!'
117
+ # else puts 'no fairy...'
118
+ # end
119
+ #
120
+ def ===( object )
121
+ !!(@regexp =~ object)
122
+ end
123
+
124
+ #
125
+ # Compares to Wildcards for equality.
126
+ #
127
+ # Two wildcards are equal, if they were constructed from the
128
+ # same string and have the same #casefold?().
129
+ #
130
+ def eql?( that )
131
+ return false unless that.is_a?(Wildcard)
132
+ @source == that.source && @casefold == that.casefold
133
+ end
134
+
135
+ alias_method :==, :eql?
136
+ alias_method :casefold?, :casefold
137
+
138
+ private
139
+
140
+ #
141
+ # Converts the wildcard string into a Regexp.
142
+ # A simple parser, I just threw it in there, no
143
+ # optimizations.
144
+ #
145
+ def compile
146
+ ptr = 0
147
+ compiled = '^'
148
+ while ptr < @source.length
149
+ snip = @source[ptr..-1]
150
+ if snip.scan(%r{^\\\\}).first
151
+ compiled << '\\\\'
152
+ ptr += 2
153
+ elsif snip.scan(%r{^\\\?}).first
154
+ compiled << '\\?'
155
+ ptr += 2
156
+ elsif snip.scan(%r{^\\\*}).first
157
+ compiled << '\\*'
158
+ ptr += 2
159
+ elsif snip.scan(%r{^\?}).first
160
+ compiled << '.'
161
+ ptr += 1
162
+ elsif snip.scan(%r{^\*}).first
163
+ compiled << '.*'
164
+ ptr += 1
165
+ elsif group = snip.scan(%r{^\[(?:\\\]|[^\]])+\]}).first
166
+ ptr += group.length
167
+ group = group[1..-2] # remove []
168
+ group = group.gsub(%r{\\\]}) { ']' }
169
+ compiled << '[' << Regexp.quote(group) << ']'
170
+ else
171
+ compiled << Regexp.quote(@source[ptr..ptr])
172
+ ptr += 1
173
+ end
174
+ end
175
+ compiled + '$'
176
+ end
177
+
178
+ end
179
+
@@ -0,0 +1,59 @@
1
+ require 'bacon'
2
+ require 'joker'
3
+
4
+ describe 'A Wildcard' do
5
+
6
+ before do
7
+ @wild ||= Wildcard['Fairy?ake*']
8
+ @wildi ||= Wildcard['Fairy?ake*\?', true]
9
+ @wildc ||= Wildcard['Fairy[cf]ake[!\\]]']
10
+ end
11
+
12
+ it 'should be constructed correctly' do
13
+ @wild.casefold?.should.be.false
14
+ @wildi.casefold?.should.be.true
15
+ @wildc.casefold?.should.be.false
16
+ regexp = @wild.instance_variable_get(:@regexp)
17
+ regexpi = @wildi.instance_variable_get(:@regexp)
18
+ regexpc = @wildc.instance_variable_get(:@regexp)
19
+ regexp.should.be == /^Fairy.ake.*$/
20
+ regexpi.should.be == /^Fairy.ake.*\?$/i
21
+ regexpc.should.be == /^Fairy[cf]ake[!\]]$/
22
+ end
23
+
24
+ it 'should match correct strings' do
25
+ @wild.should =~ 'Fairycake'
26
+ @wild.should =~ 'Fairyfakes'
27
+ @wild.should =~ 'Fairylake is a cool place'
28
+ end
29
+
30
+ it 'should not match incorrcet strings' do
31
+ @wild.should.not =~ 'Dairycake'
32
+ @wild.should.not =~ 'Fairysteakes'
33
+ @wild.should.not =~ 'fairycake'
34
+ end
35
+
36
+ it 'should match case insensitive' do
37
+ @wildi.should =~ 'FairyCake?'
38
+ @wildi.should =~ 'fairyfakes?'
39
+ @wildi.should =~ 'FairyLake IS A COOL Place?'
40
+ end
41
+
42
+ it 'should handle escapes correctly' do
43
+ wild = Wildcard['\\\\a\\?b\\*c\\d.][+'] # \\a\?b\*c\d.][+
44
+ regexp = wild.instance_variable_get(:@regexp)
45
+ regexp.should.be == /^\\a\?b\*c\\d\.\]\[\+$/
46
+ end
47
+
48
+ it 'should quote correctly' do
49
+ Wildcard.quote('*?\\').should.be == '\\*\\?\\\\' # *?\ --> \*\?\\
50
+ Wildcard.quote('\\\\').should.be == '\\\\\\\\' # \\ --> \\\\
51
+ end
52
+
53
+ it 'should know about character classes' do
54
+ @wildc.should =~ 'Fairycake!'
55
+ @wildc.should =~ 'Fairyfake]'
56
+ end
57
+
58
+ end
59
+
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: joker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Fabian Streitel
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-15 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Joker is a simple wildcard implementation that works much like Regexps
17
+ email: karottenreibe@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE.txt
24
+ - README.markdown
25
+ files:
26
+ - HISTORY.markdown
27
+ - LICENSE.txt
28
+ - README.markdown
29
+ - Rakefile
30
+ - VERSION
31
+ - lib/joker.rb
32
+ - test/test_joker.rb
33
+ has_rdoc: true
34
+ homepage: http://karottenreibe.github.com/joker
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project: k-gems
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: Joker is a simple wildcard implementation that works much like Regexps
61
+ test_files:
62
+ - test/test_joker.rb