mustermann 1.0.1 → 1.0.2.rc1
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 +4 -4
- data/.gitignore +18 -0
- data/.rspec +5 -0
- data/.travis.yml +25 -0
- data/.yardopts +3 -0
- data/Gemfile +7 -0
- data/README.md +230 -799
- data/Rakefile +27 -0
- data/mustermann-contrib/LICENSE +23 -0
- data/mustermann-contrib/README.md +1155 -0
- data/mustermann-contrib/examples/highlighting.rb +35 -0
- data/mustermann-contrib/highlighting.png +0 -0
- data/mustermann-contrib/irb.png +0 -0
- data/mustermann-contrib/lib/mustermann/cake.rb +19 -0
- data/mustermann-contrib/lib/mustermann/express.rb +38 -0
- data/mustermann-contrib/lib/mustermann/file_utils.rb +218 -0
- data/mustermann-contrib/lib/mustermann/file_utils/glob_pattern.rb +40 -0
- data/mustermann-contrib/lib/mustermann/fileutils.rb +1 -0
- data/mustermann-contrib/lib/mustermann/flask.rb +199 -0
- data/mustermann-contrib/lib/mustermann/pyramid.rb +29 -0
- data/mustermann-contrib/lib/mustermann/rails.rb +47 -0
- data/mustermann-contrib/lib/mustermann/shell.rb +57 -0
- data/mustermann-contrib/lib/mustermann/simple.rb +51 -0
- data/mustermann-contrib/lib/mustermann/string_scanner.rb +314 -0
- data/mustermann-contrib/lib/mustermann/strscan.rb +1 -0
- data/mustermann-contrib/lib/mustermann/template.rb +63 -0
- data/mustermann-contrib/lib/mustermann/uri_template.rb +1 -0
- data/mustermann-contrib/lib/mustermann/versions.rb +47 -0
- data/mustermann-contrib/lib/mustermann/visualizer.rb +39 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlight.rb +138 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter.rb +38 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ad_hoc.rb +95 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ast.rb +103 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/composite.rb +46 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/dummy.rb +19 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/regular.rb +105 -0
- data/mustermann-contrib/lib/mustermann/visualizer/pattern_extension.rb +69 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/ansi.rb +24 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/generic.rb +47 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/hansi_template.rb +35 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/html.rb +51 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/sexp.rb +38 -0
- data/mustermann-contrib/lib/mustermann/visualizer/tree.rb +64 -0
- data/mustermann-contrib/lib/mustermann/visualizer/tree_renderer.rb +79 -0
- data/mustermann-contrib/mustermann-contrib.gemspec +19 -0
- data/mustermann-contrib/spec/cake_spec.rb +91 -0
- data/mustermann-contrib/spec/express_spec.rb +210 -0
- data/mustermann-contrib/spec/file_utils_spec.rb +120 -0
- data/mustermann-contrib/spec/flask_spec.rb +362 -0
- data/mustermann-contrib/spec/flask_subclass_spec.rb +369 -0
- data/mustermann-contrib/spec/pattern_extension_spec.rb +50 -0
- data/mustermann-contrib/spec/pyramid_spec.rb +102 -0
- data/mustermann-contrib/spec/rails_spec.rb +648 -0
- data/mustermann-contrib/spec/shell_spec.rb +148 -0
- data/mustermann-contrib/spec/simple_spec.rb +269 -0
- data/mustermann-contrib/spec/string_scanner_spec.rb +272 -0
- data/mustermann-contrib/spec/template_spec.rb +842 -0
- data/mustermann-contrib/spec/visualizer_spec.rb +199 -0
- data/mustermann-contrib/theme.png +0 -0
- data/mustermann-contrib/tree.png +0 -0
- data/mustermann/LICENSE +23 -0
- data/mustermann/README.md +853 -0
- data/{bench → mustermann/bench}/capturing.rb +0 -0
- data/{bench → mustermann/bench}/regexp.rb +0 -0
- data/{bench → mustermann/bench}/simple_vs_sinatra.rb +0 -0
- data/{bench → mustermann/bench}/template_vs_addressable.rb +0 -0
- data/{lib → mustermann/lib}/mustermann.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/boundaries.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/compiler.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/expander.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/node.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/param_scanner.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/parser.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/pattern.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/template_generator.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/transformer.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/translator.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/validation.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/caster.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/composite.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/concat.rb +13 -2
- data/{lib → mustermann/lib}/mustermann/equality_map.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/error.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/expander.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/extension.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/identity.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/mapper.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/pattern.rb +1 -1
- data/{lib → mustermann/lib}/mustermann/pattern_cache.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regexp.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regexp_based.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regular.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/simple_match.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra.rb +1 -1
- data/{lib → mustermann/lib}/mustermann/sinatra/parser.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra/safe_renderer.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra/try_convert.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/to_pattern.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/version.rb +1 -1
- data/{mustermann.gemspec → mustermann/mustermann.gemspec} +0 -0
- data/{spec → mustermann/spec}/ast_spec.rb +0 -0
- data/{spec → mustermann/spec}/composite_spec.rb +0 -0
- data/{spec → mustermann/spec}/concat_spec.rb +12 -0
- data/{spec → mustermann/spec}/equality_map_spec.rb +0 -0
- data/{spec → mustermann/spec}/expander_spec.rb +0 -0
- data/{spec → mustermann/spec}/extension_spec.rb +0 -0
- data/{spec → mustermann/spec}/identity_spec.rb +0 -0
- data/{spec → mustermann/spec}/mapper_spec.rb +0 -0
- data/{spec → mustermann/spec}/mustermann_spec.rb +0 -0
- data/{spec → mustermann/spec}/pattern_spec.rb +0 -0
- data/{spec → mustermann/spec}/regexp_based_spec.rb +0 -0
- data/{spec → mustermann/spec}/regular_spec.rb +0 -0
- data/{spec → mustermann/spec}/simple_match_spec.rb +0 -0
- data/{spec → mustermann/spec}/sinatra_spec.rb +0 -0
- data/{spec → mustermann/spec}/to_pattern_spec.rb +0 -0
- data/support/lib/support.rb +7 -0
- data/support/lib/support/coverage.rb +23 -0
- data/support/lib/support/env.rb +19 -0
- data/support/lib/support/expand_matcher.rb +28 -0
- data/support/lib/support/generate_template_matcher.rb +27 -0
- data/support/lib/support/match_matcher.rb +39 -0
- data/support/lib/support/pattern.rb +42 -0
- data/support/lib/support/projects.rb +20 -0
- data/support/lib/support/scan_matcher.rb +63 -0
- data/support/support.gemspec +27 -0
- metadata +128 -58
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -10,8 +10,19 @@ module Mustermann
|
|
10
10
|
# @!visibility private
|
11
11
|
def +(other)
|
12
12
|
other &&= Mustermann.new(other, type: :identity, **options)
|
13
|
-
|
14
|
-
|
13
|
+
if (patterns = look_ahead(other)) && !patterns.empty?
|
14
|
+
concat = (self + patterns.inject(:+))
|
15
|
+
concat + other.patterns.slice(patterns.length..-1).inject(:+)
|
16
|
+
else
|
17
|
+
return super unless native = native_concat(other)
|
18
|
+
self.class.new(native, **options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @!visibility private
|
23
|
+
def look_ahead(other)
|
24
|
+
return unless other.is_a?(Concat)
|
25
|
+
other.patterns.take_while(&method(:native_concat?))
|
15
26
|
end
|
16
27
|
|
17
28
|
# @!visibility private
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -226,7 +226,7 @@ module Mustermann
|
|
226
226
|
# warn "does not support expanding"
|
227
227
|
# end
|
228
228
|
#
|
229
|
-
# Expanding is supported by almost all patterns (notable
|
229
|
+
# Expanding is supported by almost all patterns (notable exceptions are {Mustermann::Shell},
|
230
230
|
# {Mustermann::Regular} and {Mustermann::Simple}).
|
231
231
|
#
|
232
232
|
# Union {Mustermann::Composite} patterns (with the | operator) support expanding if all
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -42,7 +42,7 @@ module Mustermann
|
|
42
42
|
# If a string is supplied, it is treated as a fully escaped Sinatra pattern.
|
43
43
|
#
|
44
44
|
# If the other pattern is also a Sintara pattern, it might join the two to a third
|
45
|
-
# sinatra pattern instead of generating a composite for
|
45
|
+
# sinatra pattern instead of generating a composite for efficiency reasons.
|
46
46
|
#
|
47
47
|
# This only happens if the sinatra pattern behaves exactly the same as a composite
|
48
48
|
# would in regards to matching, parsing, expanding and template generation.
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -57,6 +57,18 @@ describe Mustermann::Concat do
|
|
57
57
|
its(:class) { should be == Mustermann::Concat }
|
58
58
|
its(:to_s) { should be == '(sinatra:"/:foo" + rails:"/:bar" + sinatra:"/:baz")' }
|
59
59
|
end
|
60
|
+
|
61
|
+
context "sinatra + (sinatra + regular)" do
|
62
|
+
subject(:pattern) { Mustermann.new("/foo") + (Mustermann.new("/bar") + Mustermann.new(/baz/)) }
|
63
|
+
its(:class) { should be == Mustermann::Concat }
|
64
|
+
its(:to_s) { should be == '(sinatra:"/foo/bar" + regular:"baz")' }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "sinatra + (sinatra + rails (different options) + sinatra)" do
|
68
|
+
subject(:pattern) { Mustermann.new("/foo") + (Mustermann.new("/bar") + Mustermann.new("/baz", type: :rails, uri_decode: false) + Mustermann.new("/boo")) }
|
69
|
+
its(:class) { should be == Mustermann::Concat }
|
70
|
+
its(:to_s) { should be == '(sinatra:"/foo/bar" + rails:"/baz" + sinatra:"/boo")' }
|
71
|
+
end
|
60
72
|
end
|
61
73
|
|
62
74
|
subject(:pattern) { Mustermann::Concat.new("/:foo", "/:bar") }
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
require 'support/projects'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
6
|
+
[
|
7
|
+
SimpleCov::Formatter::HTMLFormatter,
|
8
|
+
Coveralls::SimpleCov::Formatter
|
9
|
+
]
|
10
|
+
)
|
11
|
+
|
12
|
+
SimpleCov.start do
|
13
|
+
project_name 'mustermann'
|
14
|
+
minimum_coverage 100
|
15
|
+
coverage_dir '.coverage'
|
16
|
+
|
17
|
+
add_filter "/spec/"
|
18
|
+
add_filter "/support/"
|
19
|
+
|
20
|
+
Support::Projects.each do |project|
|
21
|
+
add_group project.sub('mustermann-', ''), "/#{project}/lib"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
if RUBY_VERSION < '2.1.0'
|
2
|
+
$stderr.puts "needs Ruby 2.1.0, you're running #{RUBY_VERSION}"
|
3
|
+
exit 1
|
4
|
+
end
|
5
|
+
|
6
|
+
RUBY_ENGINE ||= 'ruby'
|
7
|
+
ENV['RACK_ENV'] = 'test'
|
8
|
+
|
9
|
+
require 'tool/warning_filter'
|
10
|
+
$-w = true
|
11
|
+
|
12
|
+
require 'rspec'
|
13
|
+
require 'rspec/its'
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.expect_with :rspec do |c|
|
17
|
+
c.syntax = [:should, :expect]
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
RSpec::Matchers.define :expand do |behavior = nil, **values|
|
2
|
+
match do |pattern|
|
3
|
+
@string ||= nil
|
4
|
+
begin
|
5
|
+
expanded = pattern.expand(behavior, 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 do |pattern|
|
18
|
+
message = "expected %p to be expandable with %p" % [pattern, values]
|
19
|
+
message << " (%p behavior)" % behavior if behavior
|
20
|
+
expanded = pattern.expand(behavior, values)
|
21
|
+
message << " and result in %p, but got %p" % [@string, expanded] if @string
|
22
|
+
message
|
23
|
+
end
|
24
|
+
|
25
|
+
failure_message_when_negated do |pattern|
|
26
|
+
"expected %p not to be expandable with %p" % [pattern, values]
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
RSpec::Matchers.define :generate_template do |template|
|
2
|
+
match { |pattern| pattern.to_templates.include? template }
|
3
|
+
|
4
|
+
failure_message do |pattern|
|
5
|
+
"expected %p to generate template %p, but only generated %s" % [
|
6
|
+
pattern, template, pattern.to_templates.map(&:inspect).join(', ')
|
7
|
+
]
|
8
|
+
end
|
9
|
+
|
10
|
+
failure_message_when_negated do |pattern|
|
11
|
+
"expected %p not to generate template %p" % [ pattern, template ]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec::Matchers.define :generate_templates do |*templates|
|
16
|
+
match { |pattern| pattern.to_templates.sort == templates.sort }
|
17
|
+
|
18
|
+
failure_message do |pattern|
|
19
|
+
"expected %p to generate templates %p, but generated %p" % [
|
20
|
+
pattern, templates.sort, pattern.to_templates.sort
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
failure_message_when_negated do |pattern|
|
25
|
+
"expected %p not to generate templates %p" % [ pattern, templates ]
|
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 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 actual.respond_to? :to_ast
|
23
|
+
require 'mustermann/visualizer/tree_renderer'
|
24
|
+
tree = Mustermann::Visualizer::TreeRenderer.render(actual)
|
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_when_negated do |actual|
|
35
|
+
"expected %p not to match %p" % [
|
36
|
+
actual.to_s, expected
|
37
|
+
]
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Support
|
4
|
+
module Pattern
|
5
|
+
extend RSpec::Matchers::DSL
|
6
|
+
|
7
|
+
def pattern(pattern, options = nil, &block)
|
8
|
+
description = "pattern %p" % pattern
|
9
|
+
|
10
|
+
if options
|
11
|
+
description << " with options %p" % [options]
|
12
|
+
instance = subject_for(pattern, options)
|
13
|
+
else
|
14
|
+
instance = subject_for(pattern)
|
15
|
+
end
|
16
|
+
|
17
|
+
context description do
|
18
|
+
subject(:pattern, &instance)
|
19
|
+
its(:to_s) { should be == pattern }
|
20
|
+
its(:inspect) { should be == "#<#{described_class}:#{pattern.inspect}>" }
|
21
|
+
its(:names) { should be_an(Array) }
|
22
|
+
its(:to_templates) { should be == [pattern] } if described_class.name == "Mustermann::Template"
|
23
|
+
|
24
|
+
example 'string should be immune to external change' do
|
25
|
+
subject.to_s.replace "NOT THE PATTERN"
|
26
|
+
subject.to_s.should be == pattern
|
27
|
+
end
|
28
|
+
|
29
|
+
instance_eval(&block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def subject_for(pattern, *args)
|
34
|
+
instance = Timeout.timeout(1) { described_class.new(pattern, *args) }
|
35
|
+
proc { instance }
|
36
|
+
rescue Timeout::Error => error
|
37
|
+
proc { raise Timeout::Error, "could not compile #{pattern.inspect} in time", error.backtrace }
|
38
|
+
rescue Exception => error
|
39
|
+
proc { raise error }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Support
|
2
|
+
module Projects
|
3
|
+
include Enumerable
|
4
|
+
extend self
|
5
|
+
|
6
|
+
def base
|
7
|
+
File.expand_path('../../../..', __FILE__)
|
8
|
+
end
|
9
|
+
|
10
|
+
def projects
|
11
|
+
@@projects ||= Dir.chdir(base) do
|
12
|
+
Dir['mustermann*/*.gemspec'].map { |f| File.dirname(f) }.sort
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def each(&block)
|
17
|
+
projects.each(&block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Support
|
2
|
+
module ScanMatcher
|
3
|
+
extend RSpec::Matchers::DSL
|
4
|
+
|
5
|
+
def scan(pattern, **options)
|
6
|
+
give_scan_result(:scan, pattern, **options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def check(pattern, **options)
|
10
|
+
give_scan_result(:check, pattern, **options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def scan_until(pattern, **options)
|
14
|
+
give_scan_result(:scan_until, pattern, **options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_until(pattern, **options)
|
18
|
+
give_scan_result(:check_until, pattern, **options)
|
19
|
+
end
|
20
|
+
|
21
|
+
matcher :give_scan_result do |method_name, pattern, **options|
|
22
|
+
def result_expectations
|
23
|
+
@result_expectations ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def expect_result(description, expected, &block)
|
27
|
+
result_expectations << Proc.new do |result|
|
28
|
+
if !block.call(result)
|
29
|
+
"expected %p to %s %p matching %s" % [ result.scanner, method_name, pattern, description ]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
match do |scanner|
|
35
|
+
scanned = scanner.public_send(method_name, pattern, **options)
|
36
|
+
scanned and result_expectations.all? { |e| !e.call(scanned) }
|
37
|
+
end
|
38
|
+
|
39
|
+
chain(:matching_substring) do |substring|
|
40
|
+
expected_result("the substring %p" % substring) { |r| r.to_s == substring }
|
41
|
+
end
|
42
|
+
|
43
|
+
chain(:matching_length) do |length|
|
44
|
+
expected_result("%d characters" % length) { |r| r.length == length }
|
45
|
+
end
|
46
|
+
|
47
|
+
chain(:matching_params) do |params|
|
48
|
+
expected_result("with params %p" % [params]) { |r| r.params == params }
|
49
|
+
end
|
50
|
+
|
51
|
+
failure_message do |scanner|
|
52
|
+
if scanned = scanner.public_send(method_name, pattern, **options)
|
53
|
+
message = result_expectations.inject(nil) { |m,e| m || e.call(scanned) }
|
54
|
+
end
|
55
|
+
message || "expected %p to %s %p" % [ scanner, method_name, pattern ]
|
56
|
+
end
|
57
|
+
|
58
|
+
failure_message_when_negated do |scanner|
|
59
|
+
"expected %p not to %s %p" % [ scanner, method_name, pattern ]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|