mustermann 0.0.1 → 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/.travis.yml +4 -3
- data/.yardopts +1 -0
- data/README.md +53 -10
- data/Rakefile +4 -1
- data/bench/capturing.rb +42 -9
- data/bench/template_vs_addressable.rb +3 -0
- data/internals.md +64 -0
- data/lib/mustermann.rb +14 -5
- data/lib/mustermann/ast/compiler.rb +150 -0
- data/lib/mustermann/ast/expander.rb +112 -0
- data/lib/mustermann/ast/node.rb +155 -0
- data/lib/mustermann/ast/parser.rb +136 -0
- data/lib/mustermann/ast/pattern.rb +89 -0
- data/lib/mustermann/ast/transformer.rb +121 -0
- data/lib/mustermann/ast/translator.rb +111 -0
- data/lib/mustermann/ast/tree_renderer.rb +29 -0
- data/lib/mustermann/ast/validation.rb +40 -0
- data/lib/mustermann/error.rb +4 -12
- data/lib/mustermann/extension.rb +3 -6
- data/lib/mustermann/identity.rb +4 -4
- data/lib/mustermann/pattern.rb +34 -5
- data/lib/mustermann/rails.rb +7 -16
- data/lib/mustermann/regexp_based.rb +4 -4
- data/lib/mustermann/shell.rb +4 -4
- data/lib/mustermann/simple.rb +1 -1
- data/lib/mustermann/simple_match.rb +2 -2
- data/lib/mustermann/sinatra.rb +10 -20
- data/lib/mustermann/template.rb +11 -104
- data/lib/mustermann/version.rb +1 -1
- data/mustermann.gemspec +1 -1
- data/spec/extension_spec.rb +143 -0
- data/spec/mustermann_spec.rb +41 -0
- data/spec/pattern_spec.rb +16 -6
- data/spec/rails_spec.rb +77 -9
- data/spec/sinatra_spec.rb +6 -0
- data/spec/support.rb +5 -78
- data/spec/support/coverage.rb +18 -0
- data/spec/support/env.rb +6 -0
- data/spec/support/expand_matcher.rb +27 -0
- data/spec/support/match_matcher.rb +39 -0
- data/spec/support/pattern.rb +28 -0
- metadata +43 -43
- data/.test_queue_stats +0 -0
- data/lib/mustermann/ast.rb +0 -403
- data/spec/ast_spec.rb +0 -8
data/spec/pattern_spec.rb
CHANGED
@@ -2,15 +2,25 @@ require 'support'
|
|
2
2
|
require 'mustermann/pattern'
|
3
3
|
|
4
4
|
describe Mustermann::Pattern do
|
5
|
-
|
6
|
-
|
5
|
+
describe :=== do
|
6
|
+
it 'raises a NotImplementedError when used directly' do
|
7
|
+
expect { described_class.new("") === "" }.to raise_error(NotImplementedError)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
+
describe :initialize do
|
12
|
+
it 'raises an ArgumentError for unknown options' do
|
13
|
+
expect { described_class.new("", foo: :bar) }.to raise_error(ArgumentError)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'does not complain about unknown options if ignore_unknown_options is enabled' do
|
17
|
+
expect { described_class.new("", foo: :bar, ignore_unknown_options: true) }.not_to raise_error
|
18
|
+
end
|
11
19
|
end
|
12
20
|
|
13
|
-
|
14
|
-
|
21
|
+
describe :expand do
|
22
|
+
subject(:pattern) { described_class.new("") }
|
23
|
+
it { should_not respond_to(:expand) }
|
24
|
+
it { expect { pattern.expand }.to raise_error(NotImplementedError) }
|
15
25
|
end
|
16
26
|
end
|
data/spec/rails_spec.rb
CHANGED
@@ -7,23 +7,35 @@ describe Mustermann::Rails do
|
|
7
7
|
pattern '' do
|
8
8
|
it { should match('') }
|
9
9
|
it { should_not match('/') }
|
10
|
+
|
11
|
+
it { should expand.to('') }
|
12
|
+
it { should_not expand(a: 1) }
|
10
13
|
end
|
11
14
|
|
12
15
|
pattern '/' do
|
13
16
|
it { should match('/') }
|
14
17
|
it { should_not match('/foo') }
|
18
|
+
|
19
|
+
it { should expand.to('/') }
|
20
|
+
it { should_not expand(a: 1) }
|
15
21
|
end
|
16
22
|
|
17
23
|
pattern '/foo' do
|
18
24
|
it { should match('/foo') }
|
19
25
|
it { should_not match('/bar') }
|
20
26
|
it { should_not match('/foo.bar') }
|
27
|
+
|
28
|
+
it { should expand.to('/foo') }
|
29
|
+
it { should_not expand(a: 1) }
|
21
30
|
end
|
22
31
|
|
23
32
|
pattern '/foo/bar' do
|
24
33
|
it { should match('/foo/bar') }
|
25
34
|
it { should_not match('/foo%2Fbar') }
|
26
35
|
it { should_not match('/foo%2fbar') }
|
36
|
+
|
37
|
+
it { should expand.to('/foo/bar') }
|
38
|
+
it { should_not expand(a: 1) }
|
27
39
|
end
|
28
40
|
|
29
41
|
pattern '/:foo' do
|
@@ -38,13 +50,23 @@ describe Mustermann::Rails do
|
|
38
50
|
it { should_not match('/') }
|
39
51
|
it { should_not match('/foo/') }
|
40
52
|
|
41
|
-
example { pattern.params('/foo').should be == {"foo" => "foo"} }
|
42
|
-
example { pattern.params('/f%20o').should be == {"foo" => "f o"} }
|
53
|
+
example { pattern.params('/foo') .should be == {"foo" => "foo"} }
|
54
|
+
example { pattern.params('/f%20o') .should be == {"foo" => "f o"} }
|
43
55
|
example { pattern.params('').should be_nil }
|
56
|
+
|
57
|
+
it { should expand(foo: 'bar') .to('/bar') }
|
58
|
+
it { should expand(foo: 'b r') .to('/b%20r') }
|
59
|
+
it { should expand(foo: 'foo/bar') .to('/foo%2Fbar') }
|
60
|
+
|
61
|
+
it { should_not expand(foo: 'foo', bar: 'bar') }
|
62
|
+
it { should_not expand(bar: 'bar') }
|
63
|
+
it { should_not expand }
|
44
64
|
end
|
45
65
|
|
46
66
|
pattern '/föö' do
|
47
67
|
it { should match("/f%C3%B6%C3%B6") }
|
68
|
+
it { should expand.to("/f%C3%B6%C3%B6") }
|
69
|
+
it { should_not expand(a: 1) }
|
48
70
|
end
|
49
71
|
|
50
72
|
pattern "/:foo/:bar" do
|
@@ -59,48 +81,72 @@ describe Mustermann::Rails do
|
|
59
81
|
|
60
82
|
example { pattern.params('/bar/foo').should be == {"foo" => "bar", "bar" => "foo"} }
|
61
83
|
example { pattern.params('').should be_nil }
|
84
|
+
|
85
|
+
it { should expand(foo: 'foo', bar: 'bar').to('/foo/bar') }
|
86
|
+
it { should_not expand(foo: 'foo') }
|
87
|
+
it { should_not expand(bar: 'bar') }
|
62
88
|
end
|
63
89
|
|
64
90
|
pattern '/hello/:person' do
|
65
91
|
it { should match('/hello/Frank').capturing person: 'Frank' }
|
92
|
+
it { should expand(person: 'Frank') .to '/hello/Frank' }
|
93
|
+
it { should expand(person: 'Frank?') .to '/hello/Frank%3F' }
|
66
94
|
end
|
67
95
|
|
68
96
|
pattern '/?:foo?/?:bar?' do
|
69
97
|
it { should match('/?hello?/?world?').capturing foo: 'hello', bar: 'world' }
|
70
98
|
it { should_not match('/hello/world/') }
|
99
|
+
it { should expand(foo: 'hello', bar: 'world').to('/%3Fhello%3F/%3Fworld%3F') }
|
71
100
|
end
|
72
101
|
|
73
102
|
pattern '/:foo_bar' do
|
74
103
|
it { should match('/hello').capturing foo_bar: 'hello' }
|
104
|
+
it { should expand(foo_bar: 'hello').to('/hello') }
|
75
105
|
end
|
76
106
|
|
77
107
|
pattern '/*foo' do
|
78
108
|
it { should match('/') .capturing foo: '' }
|
79
109
|
it { should match('/foo') .capturing foo: 'foo' }
|
80
110
|
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
111
|
+
|
112
|
+
it { should expand .to('/') }
|
113
|
+
it { should expand(foo: nil) .to('/') }
|
114
|
+
it { should expand(foo: '') .to('/') }
|
115
|
+
it { should expand(foo: 'foo') .to('/foo') }
|
116
|
+
it { should expand(foo: 'foo/bar') .to('/foo/bar') }
|
117
|
+
it { should expand(foo: 'foo.bar') .to('/foo.bar') }
|
81
118
|
end
|
82
119
|
|
83
120
|
pattern '/:foo/*bar' do
|
84
|
-
it { should match("/foo/bar/baz") .capturing foo: 'foo',
|
85
|
-
it { should match("/foo/")
|
86
|
-
it { should match(
|
121
|
+
it { should match("/foo/bar/baz") .capturing foo: 'foo', bar: 'bar/baz' }
|
122
|
+
it { should match("/foo%2Fbar/baz") .capturing foo: 'foo%2Fbar', bar: 'baz' }
|
123
|
+
it { should match("/foo/") .capturing foo: 'foo', bar: '' }
|
124
|
+
it { should match('/h%20w/h%20a%20y') .capturing foo: 'h%20w', bar: 'h%20a%20y' }
|
87
125
|
it { should_not match('/foo') }
|
126
|
+
|
127
|
+
it { should expand(foo: 'foo') .to('/foo/') }
|
128
|
+
it { should expand(foo: 'foo', bar: 'bar') .to('/foo/bar') }
|
129
|
+
it { should expand(foo: 'foo', bar: 'foo/bar') .to('/foo/foo/bar') }
|
130
|
+
it { should expand(foo: 'foo/bar', bar: 'bar') .to('/foo%2Fbar/bar') }
|
88
131
|
end
|
89
132
|
|
90
133
|
pattern '/test$/' do
|
91
134
|
it { should match('/test$/') }
|
135
|
+
it { should expand.to('/test$/') }
|
92
136
|
end
|
93
137
|
|
94
138
|
pattern '/te+st/' do
|
95
139
|
it { should match('/te+st/') }
|
96
140
|
it { should_not match('/test/') }
|
97
141
|
it { should_not match('/teest/') }
|
142
|
+
it { should expand.to('/te+st/') }
|
98
143
|
end
|
99
144
|
|
100
145
|
pattern "/path with spaces" do
|
101
|
-
it { should match('/path%20with%20spaces')
|
102
|
-
it { should match('/path%2Bwith%2Bspaces')
|
103
|
-
it { should match('/path+with+spaces')
|
146
|
+
it { should match('/path%20with%20spaces') }
|
147
|
+
it { should match('/path%2Bwith%2Bspaces') }
|
148
|
+
it { should match('/path+with+spaces') }
|
149
|
+
it { should expand.to('/path%20with%20spaces') }
|
104
150
|
end
|
105
151
|
|
106
152
|
pattern '/foo&bar' do
|
@@ -110,6 +156,7 @@ describe Mustermann::Rails do
|
|
110
156
|
pattern '/*a/:foo/*b/*c' do
|
111
157
|
it { should match('/bar/foo/bling/baz/boom').capturing a: 'bar', foo: 'foo', b: 'bling', c: 'baz/boom' }
|
112
158
|
example { pattern.params('/bar/foo/bling/baz/boom').should be == { "a" => 'bar', "foo" => 'foo', "b" => 'bling', "c" => 'baz/boom' } }
|
159
|
+
it { should expand(a: 'bar', foo: 'foo', b: 'bling', c: 'baz/boom').to('/bar/foo/bling/baz/boom') }
|
113
160
|
end
|
114
161
|
|
115
162
|
pattern '/test.bar' do
|
@@ -118,7 +165,7 @@ describe Mustermann::Rails do
|
|
118
165
|
end
|
119
166
|
|
120
167
|
pattern '/:file.:ext' do
|
121
|
-
it { should match('/pony.jpg')
|
168
|
+
it { should match('/pony.jpg') .capturing file: 'pony', ext: 'jpg' }
|
122
169
|
it { should match('/pony%2Ejpg') .capturing file: 'pony', ext: 'jpg' }
|
123
170
|
it { should match('/pony%2ejpg') .capturing file: 'pony', ext: 'jpg' }
|
124
171
|
|
@@ -129,6 +176,7 @@ describe Mustermann::Rails do
|
|
129
176
|
it { should match('/pony正..jpg') .capturing file: 'pony正.', ext: 'jpg' }
|
130
177
|
|
131
178
|
it { should_not match('/.jpg') }
|
179
|
+
it { should expand(file: 'pony', ext: 'jpg').to('/pony.jpg') }
|
132
180
|
end
|
133
181
|
|
134
182
|
pattern '/:a(x)' do
|
@@ -138,12 +186,17 @@ describe Mustermann::Rails do
|
|
138
186
|
it { should match('/ax') .capturing a: 'a' }
|
139
187
|
it { should match('/axax') .capturing a: 'axa' }
|
140
188
|
it { should match('/axaxx') .capturing a: 'axax' }
|
189
|
+
it { should expand(a: 'x').to('/xx') }
|
190
|
+
it { should expand(a: 'a').to('/ax') }
|
141
191
|
end
|
142
192
|
|
143
193
|
pattern '/:user(@:host)' do
|
144
194
|
it { should match('/foo@bar') .capturing user: 'foo', host: 'bar' }
|
145
195
|
it { should match('/foo.foo@bar') .capturing user: 'foo.foo', host: 'bar' }
|
146
196
|
it { should match('/foo@bar.bar') .capturing user: 'foo', host: 'bar.bar' }
|
197
|
+
|
198
|
+
it { should expand(user: 'foo') .to('/foo') }
|
199
|
+
it { should expand(user: 'foo', host: 'bar') .to('/foo@bar') }
|
147
200
|
end
|
148
201
|
|
149
202
|
pattern '/:file(.:ext)' do
|
@@ -154,6 +207,9 @@ describe Mustermann::Rails do
|
|
154
207
|
it { should match('/pony.png.jpg') .capturing file: 'pony.png', ext: 'jpg' }
|
155
208
|
it { should match('/pony.') .capturing file: 'pony.' }
|
156
209
|
it { should_not match('/.jpg') }
|
210
|
+
|
211
|
+
it { should expand(file: 'pony') .to('/pony') }
|
212
|
+
it { should expand(file: 'pony', ext: 'jpg') .to('/pony.jpg') }
|
157
213
|
end
|
158
214
|
|
159
215
|
pattern '/:id/test.bar' do
|
@@ -185,6 +241,9 @@ describe Mustermann::Rails do
|
|
185
241
|
it { should match('/a.b/c') .capturing a: 'a.b', b: 'c', c: nil }
|
186
242
|
it { should match('/a.b/c.d') .capturing a: 'a.b', b: 'c', c: 'd' }
|
187
243
|
it { should_not match('/a.b/c.d/e') }
|
244
|
+
|
245
|
+
it { should expand(a: ?a, b: ?b) .to('/a/b.') }
|
246
|
+
it { should expand(a: ?a, b: ?b, c: ?c) .to('/a/b.c') }
|
188
247
|
end
|
189
248
|
|
190
249
|
pattern '/:a(foo:b)' do
|
@@ -192,6 +251,9 @@ describe Mustermann::Rails do
|
|
192
251
|
it { should match('/barfoobarfoobar') .capturing a: 'barfoobar', b: 'bar' }
|
193
252
|
it { should match('/bar') .capturing a: 'bar', b: nil }
|
194
253
|
it { should_not match('/') }
|
254
|
+
|
255
|
+
it { should expand(a: ?a) .to('/a') }
|
256
|
+
it { should expand(a: ?a, b: ?b) .to('/afoob') }
|
195
257
|
end
|
196
258
|
|
197
259
|
pattern '/fo(o)' do
|
@@ -201,6 +263,8 @@ describe Mustermann::Rails do
|
|
201
263
|
it { should_not match('/') }
|
202
264
|
it { should_not match('/f') }
|
203
265
|
it { should_not match('/fooo') }
|
266
|
+
|
267
|
+
it { should expand.to('/foo') }
|
204
268
|
end
|
205
269
|
|
206
270
|
pattern '/foo?' do
|
@@ -212,6 +276,8 @@ describe Mustermann::Rails do
|
|
212
276
|
it { should_not match('/') }
|
213
277
|
it { should_not match('/f') }
|
214
278
|
it { should_not match('/fooo') }
|
279
|
+
|
280
|
+
it { should expand.to('/foo%3F') }
|
215
281
|
end
|
216
282
|
|
217
283
|
pattern '/:fOO' do
|
@@ -228,6 +294,8 @@ describe Mustermann::Rails do
|
|
228
294
|
|
229
295
|
pattern '/:foo(/:bar)/:baz' do
|
230
296
|
it { should match('/foo/bar/baz').capturing foo: 'foo', bar: 'bar', baz: 'baz' }
|
297
|
+
it { should expand(foo: ?a, baz: ?b) .to('/a/b') }
|
298
|
+
it { should expand(foo: ?a, baz: ?b, bar: ?x) .to('/a/x/b') }
|
231
299
|
end
|
232
300
|
|
233
301
|
pattern '/:foo', capture: /\d+/ do
|
data/spec/sinatra_spec.rb
CHANGED
@@ -74,6 +74,12 @@ describe Mustermann::Sinatra do
|
|
74
74
|
it { should match('') .capturing foo: nil, bar: nil }
|
75
75
|
|
76
76
|
it { should_not match('/hello/world/') }
|
77
|
+
|
78
|
+
# it { should expand(foo: 'hello') .to('/hello') }
|
79
|
+
# it { should expand(foo: 'hello', bar: 'world') .to('/hello/world') }
|
80
|
+
# it { should expand(bar: 'world') .to('//world') }
|
81
|
+
# it { should expand .to('') }
|
82
|
+
# it { should_not expand(baz: '') }
|
77
83
|
end
|
78
84
|
|
79
85
|
pattern '/:foo_bar' do
|
data/spec/support.rb
CHANGED
@@ -1,78 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
|
6
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
7
|
-
SimpleCov::Formatter::HTMLFormatter,
|
8
|
-
Coveralls::SimpleCov::Formatter
|
9
|
-
]
|
10
|
-
|
11
|
-
SimpleCov.start do
|
12
|
-
project_name 'mustermann'
|
13
|
-
minimum_coverage 100
|
14
|
-
|
15
|
-
add_filter "/spec/"
|
16
|
-
add_group 'Library', 'lib'
|
17
|
-
end
|
18
|
-
|
19
|
-
RSpec::Matchers.define :match do |expected|
|
20
|
-
match do |actual|
|
21
|
-
@captures ||= false
|
22
|
-
match = actual.match(expected)
|
23
|
-
match &&= @captures.all? { |k, v| match[k] == v } if @captures
|
24
|
-
match
|
25
|
-
end
|
26
|
-
|
27
|
-
chain :capturing do |captures|
|
28
|
-
@captures = captures
|
29
|
-
end
|
30
|
-
|
31
|
-
failure_message_for_should do |actual|
|
32
|
-
require 'pp'
|
33
|
-
match = actual.match(expected)
|
34
|
-
if match
|
35
|
-
key, value = @captures.detect { |k, v| match[k] != v }
|
36
|
-
"expected %p to capture %p as %p when matching %p, but got %p\n\nRegular Expression:\n%p" % [
|
37
|
-
actual.to_s, key, value, expected, match[key], actual.regexp
|
38
|
-
]
|
39
|
-
else
|
40
|
-
"expected %p to match %p" % [ actual, expected ]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
failure_message_for_should_not do |actual|
|
45
|
-
"expected %p not to match %p" % [
|
46
|
-
actual.to_s, expected
|
47
|
-
]
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
module Support
|
52
|
-
module Pattern
|
53
|
-
def pattern(pattern, options = nil, &block)
|
54
|
-
description = "pattern %p" % pattern
|
55
|
-
|
56
|
-
if options
|
57
|
-
description << " with options %p" % options
|
58
|
-
instance = described_class.new(pattern, options)
|
59
|
-
else
|
60
|
-
instance = described_class.new(pattern)
|
61
|
-
end
|
62
|
-
|
63
|
-
context description do
|
64
|
-
subject(:pattern) { instance }
|
65
|
-
its(:to_s) { should be == pattern }
|
66
|
-
its(:inspect) { should be == "#<#{described_class}:#{pattern.inspect}>" }
|
67
|
-
its(:names) { should be_an(Array) }
|
68
|
-
|
69
|
-
example 'string should be immune to external change' do
|
70
|
-
subject.to_s.replace "NOT THE PATTERN"
|
71
|
-
subject.to_s.should be == pattern
|
72
|
-
end
|
73
|
-
|
74
|
-
instance_eval(&block)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
1
|
+
require 'support/env'
|
2
|
+
require 'support/coverage'
|
3
|
+
require 'support/expand_matcher'
|
4
|
+
require 'support/match_matcher'
|
5
|
+
require 'support/pattern'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
if RUBY_ENGINE == 'ruby' and RUBY_VERSION < '2.1'
|
2
|
+
require 'simplecov'
|
3
|
+
require 'coveralls'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
Coveralls::SimpleCov::Formatter
|
8
|
+
]
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
project_name 'mustermann'
|
12
|
+
minimum_coverage 100
|
13
|
+
coverage_dir '.coverage'
|
14
|
+
|
15
|
+
add_filter "/spec/"
|
16
|
+
add_group 'Library', 'lib'
|
17
|
+
end
|
18
|
+
end
|
data/spec/support/env.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec::Matchers.define :expand do |values = {}|
|
2
|
+
match do |pattern|
|
3
|
+
@string ||= nil
|
4
|
+
begin
|
5
|
+
expanded = pattern.expand(values)
|
6
|
+
rescue Exception
|
7
|
+
false
|
8
|
+
else
|
9
|
+
@string ? @string == expanded : !!expanded
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
chain :to do |string|
|
14
|
+
@string = string
|
15
|
+
end
|
16
|
+
|
17
|
+
failure_message_for_should do |pattern|
|
18
|
+
message = "expected %p to be expandable with %p" % [pattern, values]
|
19
|
+
expanded = pattern.expand(values)
|
20
|
+
message << " and result in %p, but got %p" % [@string, expanded] if @string
|
21
|
+
message
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_for_should_not do |pattern|
|
25
|
+
"expected %p not to be expandable with %p" % [pattern, values]
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
RSpec::Matchers.define :match do |expected|
|
2
|
+
match do |actual|
|
3
|
+
@captures ||= false
|
4
|
+
match = actual.match(expected)
|
5
|
+
match &&= @captures.all? { |k, v| match[k] == v } if @captures
|
6
|
+
match
|
7
|
+
end
|
8
|
+
|
9
|
+
chain :capturing do |captures|
|
10
|
+
@captures = captures
|
11
|
+
end
|
12
|
+
|
13
|
+
failure_message_for_should do |actual|
|
14
|
+
require 'pp'
|
15
|
+
match = actual.match(expected)
|
16
|
+
if match
|
17
|
+
key, value = @captures.detect { |k, v| match[k] != v }
|
18
|
+
message = "expected %p to capture %p as %p when matching %p, but got %p\n\nRegular Expression:\n%p" % [
|
19
|
+
actual.to_s, key, value, expected, match[key], actual.regexp
|
20
|
+
]
|
21
|
+
|
22
|
+
if ast = actual.instance_variable_get(:@ast)
|
23
|
+
require 'mustermann/ast/tree_renderer'
|
24
|
+
tree = Mustermann::AST::TreeRenderer.render(ast)
|
25
|
+
message << "\n\nAST:\n#{tree}"
|
26
|
+
end
|
27
|
+
|
28
|
+
message
|
29
|
+
else
|
30
|
+
"expected %p to match %p" % [ actual, expected ]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
failure_message_for_should_not do |actual|
|
35
|
+
"expected %p not to match %p" % [
|
36
|
+
actual.to_s, expected
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|