diff --git a/examples/example.rb b/examples/example.rb new file mode 100644 index 0000000..af0fcdf --- /dev/null +++ b/examples/example.rb @@ -0,0 +1,234 @@ +#!/usr/bin/env ruby + +load '../lib/regexify.rb' + +# monkey patch Regexify to add 'to_s' method + +class Regexify + public + def to_s + @str + end +end + +class RegexifyWithOptions < Regexify + + @options = nil + + public + + def options + @options + end + + def options=(opt) + raise Regexify::Error.new("Illegal regex modifier string") \ + unless opt.kind_of?(NilClass) || \ + (opt.kind_of?(String) && opt.match?(/[ixm]/)) + @options = opt + end + + def initialize(opt = nil) + super() + self.options = opt + end + + # Converts Regexify object to Regexp + def regex + opts = 0 + unless @options.nil? + @options = squeeze(@options) + opts |= Regexp::IGNORECASE if @options.match?(/i/) + opts |= Regexp::EXTENDED if @options.match?(/x/) + opts |= Regexp::MULTILINE if @options.match?(/m/) + end + Regexp.new(@str, opts) + end + + protected + + def squeeze(str) + uniqs = '' + str.sub(/\s+/,'').each_char { |s| uniqs += s if !uniqs.include?(s) } + return uniqs.downcase + end +end + +class RegexifyWithAnchor < Regexify + + public + + def initialize + super + end + +# Insert an anchor: +# +# \A - Matches beginning of string. +# \Z - Matches end of string. If string ends with a newline, it matches just +# before newline +# \z - Matches end of string +# \G - Matches point where last match finished +# \b - Matches word boundaries when outside brackets; backspace (0x08) when +# inside brackets +# \B - Matches non-word boundaries + + def anchor(a) + raise Regexify::Error.new("Illegal anchor.") \ + unless a.length == 1 && a.match?(/[AZzGbB]/) + @str += "\\#{a}" + self + end + +# (?=pat) - Positive lookahead assertion: ensures that the following characters +# match pat, but doesn't include those characters in the matched text + + def pos_look_ahead(pat) + @str += "\(\?=#{pat}\)" + self + end + +# (?!pat) - Negative lookahead assertion: ensures that the following characters +# do not match pat, but doesn't include those characters in the +# matched text + + def neg_look_ahead(pat) + @str += "\(\?!#{pat}\)" + self + end + +# (?<=pat) - Positive lookbehind assertion: ensures that the preceding +# characters match pat, but doesn't include those characters in the +# matched text + + def pos_look_behind(pat) + @str += "\(\?<=#{pat}\)" + self + end + +# (? e1 + puts "\t4. " + "Regexify::Error => #{e1}" +end +puts "" +begin + t = RegexifyWithOptions.new(1) +rescue Regexify::Error => e2 + puts "\t5. " + "Regexify::Error => #{e2}" +end + + +puts "" +puts "RegexifyWithAnchor" +puts "" + +puts "\t" + RegexifyWithAnchor.new + .begin_with(:uppercase, exactly: 3) + .then(:number, '-', range: [2,10]) + .not(:alphanumeric, exactly:1) + .anchor('b') + .pos_look_ahead("boy") + .anchor('Z') + .neg_look_behind("howdy") + .end_with('!').to_s + +puts "" +puts "RegexifyANSI" +puts "" + +puts "\t" + RegexifyANSI.new + .begin_with(:uppercase, exactly: 3) + .then(:number, '-', range: [2,10]) + .not(:alphanumeric, exactly:1) + .then(:hexdigit) + .then(:punctuation) + .end_with('!').to_s + +puts "" + diff --git a/lib/regexify.rb b/lib/regexify.rb index 956669d..78301bb 100644 --- a/lib/regexify.rb +++ b/lib/regexify.rb @@ -1,9 +1,13 @@ # Where the regex magic happens class Regexify + public + # Class to raise errors class Error < StandardError; end + private + # a small list of popular regex tokens that are available with regexify PATTERNS = { number: '0-9', @@ -20,9 +24,19 @@ class Error < StandardError; end # chars that needs to be escaped in a regex ESCAPED_CHARS = %w(* . ? ^ + $ | ( ) [ ] { } \\) + protected + + # instance variables + @str = nil + @patterns = nil + @complete = nil + + public + # default constructor def initialize @str = "" + @patterns = PATTERNS @complete = false end @@ -99,8 +113,8 @@ def parse(args, exactly: nil, range: nil) def extract_regex(arg) regex_str = "" if arg.is_a? Symbol - raise Regexify::Error.new('symbol not defined in patterns') unless PATTERNS.key?(arg) - PATTERNS[arg] + raise Regexify::Error.new('symbol not defined in patterns') unless @patterns.key?(arg) + @patterns[arg] else escape(arg) end @@ -142,4 +156,5 @@ def contains_symbols?(args) end return false end + end