Method: Extruder::FileSet#build_pattern

Defined in:
lib/extruder/file_set.rb

#build_pattern(glob) ⇒ Object

Build a regular expression pattern from a file glob that can be used to narrow a selection of files from a Extruder.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/extruder/file_set.rb', line 33

def build_pattern(glob)

  scanner = StringScanner.new(glob)

  output, pos = "", 0

  # keep scanning until end of String
  until scanner.eos?

    # look for **/, *, {...}, or the end of the string
    new_chars = scanner.scan_until %r{
        \*\*/
      | /\*\*/
      | \*
      | \{[^\}]*\}
      | $
    }x

    # get the new part of the string up to the match
    before = new_chars[0, new_chars.size - scanner.matched_size]

    # get the match and new position
    match = scanner.matched
    pos = scanner.pos

    # add any literal characters to the output
    output << Regexp.escape(before) if before

    output << case match
    when "/**/"
      # /**/ matches either a "/" followed by any number
      # of characters or a single "/"
      "(/.*|/)"
    when "**/"
      # **/ matches the beginning of the path or
      # any number of characters followed by a "/"
      "(^|.*/)"
    when "*"
      # * matches any number of non-"/" characters
      "[^/]*"
    when /\{.*\}/
      # {...} is split over "," and glued back together
      # as an or condition
      "(" + match[1...-1].gsub(",", "|") + ")"
    else String
      # otherwise, we've grabbed until the end
      match
    end
  end

  if glob.include?("/")
    # if the pattern includes a /, it must match the
    # entire input, not just the end.
    @pattern = Regexp.new("^#{output}$", "i")
  else
    # anchor the pattern either at the beginning of the
    # path or at any "/" character
    @pattern = Regexp.new("(^|/)#{output}$", "i")
  end
end