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.
- data/HISTORY.markdown +6 -0
- data/LICENSE.txt +23 -0
- data/README.markdown +70 -0
- data/Rakefile +20 -0
- data/VERSION +1 -0
- data/lib/joker.rb +179 -0
- data/test/test_joker.rb +59 -0
- metadata +62 -0
data/HISTORY.markdown
ADDED
data/LICENSE.txt
ADDED
@@ -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
|
+
|
data/README.markdown
ADDED
@@ -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
|
+
|
data/Rakefile
ADDED
@@ -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
|
data/lib/joker.rb
ADDED
@@ -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
|
+
|
data/test/test_joker.rb
ADDED
@@ -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
|