Class: ShellTest::RegexpEscape

Inherits:
Regexp
  • Object
show all
Defined in:
lib/shell_test/regexp_escape.rb

Overview

RegexpEscape is a subclass of regexp that escapes all but the text in a special escape sequence. This allows the creation of complex regexps to match, for instance, console output.

The RegexpEscape.escape (or equivalently the quote) method does the work; all regexp-active characters are escaped except for characters enclosed by ‘:.’ and ‘.:’ delimiters.

RegexpEscape.escape('reg[exp]+ chars. are(quoted)')       # => 'reg\[exp\]\+\ chars\.\ are\(quoted\)'
RegexpEscape.escape('these are not: :.a(b*)c.:')          # => 'these\ are\ not:\ a(b*)c'

All-period regexps are treated specially. A single period is translated to ‘.*?’ to lazily match anything on a single line. Multiple periods are translated to ‘(?:(?m).*?)’ to lazily match anything actoss multiple lines. Use the ‘.n’ notation to specify n arbitrary characters.

RegexpEscape.escape('a:...:b:....:c')        # => 'a.*?b(?:(?m).*?)c'
RegexpEscape.escape('a:..{1}.:b')            # => 'a.{1}b'

RegexpEscape instances are initialized using the escaped input string and return the original string upon to_s.

str = %q{
a multiline
:...:
example}
r = RegexpEscape.new(str)

r =~ %q{
a multiline
matching
example}  # => true

r !~ %q{
a failing multiline
example}  # => true

r.to_s    # => str

Constant Summary collapse

ESCAPE_SEQUENCE =

matches the escape sequence

/:\..*?\.:/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str, *options) ⇒ RegexpEscape

Generates a new RegexpEscape by escaping the str, using the same options as Regexp.



82
83
84
85
# File 'lib/shell_test/regexp_escape.rb', line 82

def initialize(str, *options)
  super(RegexpEscape.escape(str), *options)
  @original_str = str
end

Class Method Details

.escape(str) ⇒ Object

Escapes regexp-active characters in str, except for character delimited by ‘:.’ and ‘.:’. See the class description for details.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/shell_test/regexp_escape.rb', line 51

def escape(str)
  substituents = []
  str.scan(ESCAPE_SEQUENCE) do
    regexp_str = $&[2...-2]
    substituents << case regexp_str
    when '.'
      ".*?"
    when /\A\.+\z/
      "(?:(?m).*?)"
    else
      regexp_str
    end
  end
  substituents << ""

  splits = str.split(ESCAPE_SEQUENCE).collect do |split|
    super(split)
  end
  splits << "" if splits.empty?

  splits.zip(substituents).to_a.flatten.join
end

.quote(str) ⇒ Object

Same as escape.



75
76
77
# File 'lib/shell_test/regexp_escape.rb', line 75

def quote(str)
  escape(str)
end

Instance Method Details

#to_sObject

Returns the original string for self



88
89
90
# File 'lib/shell_test/regexp_escape.rb', line 88

def to_s
  @original_str
end