Skip to content

Commit

Permalink
Add support for regexp matching
Browse files Browse the repository at this point in the history
  • Loading branch information
jisom-godaddy committed May 17, 2021
1 parent 323ec17 commit 70d6518
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 0 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,23 @@ TODO: fill out this section.

TODO: fill out this section.

### `ShapeOf::Regexp`

The `ShapeOf::Regexp[/regexp pattern/]` is used to match either `Regexp`s as equal or to match a `Regexp` against a `String` using `Regexp#match?`.
```ruby
shape = ShapeOf::Regexp[/foobar$/i]
shape.shape_of?("foobar") # => true
shape.shape_of?(/foobar$/i) # => true
shape.shape_of?("fOobAr\n") # => true
shape.shape_of?("\n\nfoobar\n") # => true
shape.shape_of?("foo\nbarfoo\nfoobar\nfo\nobar\n") # => true
shape.shape_of?("There once was a barfoo who foobared. Foobar") # => true
shape.shape_of?(/foobar$/) # => false
shape.shape_of?(/foobar/i) # => false
shape.shape_of?("foo\nbar\n") # => false
```

### `ShapeOf::Boolean`

TODO: fill out this section.
Expand Down
41 changes: 41 additions & 0 deletions lib/shape_of.rb
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,47 @@ def self.required?
end
end

class Regexp < Shape
@internal_class = ::Regexp

def self.shape_of?(object)
object.instance_of? @internal_class
end

def self.[](shape)
raise TypeError, "Shape must be #{::Regexp.inspect}, was #{shape.inspect}" unless shape.instance_of? ::Regexp

Class.new(self) do
@class_name = "#{superclass.name}[#{shape.inspect}]"
@shape = shape

def self.name
@class_name
end

def self.to_s
@class_name
end

def self.inspect
@class_name
end

def self.shape_of?(object)
unless object.instance_of?(::Regexp) || object.instance_of?(String)
raise TypeError, "expected #{::Regexp.inspect} or #{String.inspect}, was instead #{object.inspect}"
end

if object.instance_of?(::Regexp)
@shape == object
else # string
@shape.match?(object)
end
end
end
end
end

Numeric = Union[Integer, Float, Rational, Complex].tap do |this|
this.instance_variable_set(:@class_name, this.name.sub(/Union.*/, 'Numeric'))
end
Expand Down
21 changes: 21 additions & 0 deletions test/test_shape_of.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ def test_nothing_is_defined
assert_equal Class, ShapeOf::Nothing.class
end

def test_regexp_is_defined
assert_equal "constant", defined? ShapeOf::Regexp
assert_equal Class, ShapeOf::Regexp.class
end

def test_numeric_is_defined
assert_equal "constant", defined? ShapeOf::Numeric
assert_equal Class, ShapeOf::Numeric.class
Expand Down Expand Up @@ -279,6 +284,22 @@ def test_nothing_with_hash
refute_shape_of_many shape, [{ foo: nil }, { foo: :bar }, { hello: "world" }, [{}]]
end

# Regexp

def test_regexp
assert_operator ShapeOf::Regexp, :respond_to?, :required?
assert_predicate ShapeOf::Regexp, :required?
assert_raises(TypeError) { ShapeOf::Regexp['foobar'] }
assert_raises(TypeError) { ShapeOf::Regexp[/foobar/].shape_of?(['hello']) }

assert_shape_of_many ShapeOf::Regexp, [/foo/, //, /bar/, /bz/imx, Regexp.new('foobadfaejralj')]
refute_shape_of_many ShapeOf::Regexp, [nil, true, false, '', '/foobar/']
assert_shape_of_many ShapeOf::Regexp[/foobar/], [/foobar/, 'foobar', "\n\nfoobar\n\n", /foobar/.to_s, "qwertyuiopasdfghjklzxcvbnmfoobarqwertyuioopasdfghjklzxcvbnm"]
refute_shape_of_many ShapeOf::Regexp[/foobar/], [/fobar/, 'fobar', '']
assert_shape_of_many ShapeOf::Regexp[/^whoa/i], [/^whoa/i, 'whoa there', 'WHOA there!', "whoa hello\nwhoa there\nwhoa whoa!"]
refute_shape_of_many ShapeOf::Regexp[/^whoa/i], [/whoa/, 'hey, whoa there', " WHOA there!"]
end

# Numeric

def test_numeric
Expand Down

0 comments on commit 70d6518

Please sign in to comment.