class Dir

  # Like +glob+ but can take multiple patterns.
  #
  #   Dir.multiglob( '*.rb', '*.py' )
  #
  # Rather then constants for options multiglob accepts a trailing options
  # hash of symbol keys.
  #
  #   :noescape    File::FNM_NOESCAPE
  #   :casefold    File::FNM_CASEFOLD
  #   :pathname    File::FNM_PATHNAME
  #   :dotmatch    File::FNM_DOTMATCH
  #   :strict      File::FNM_PATHNAME && File::FNM_DOTMATCH
  #
  # It also has an option for recurse.
  #
  #   :recurse     Recurively include contents of directories.
  #
  # For example
  #
  #   Dir.multiglob( '*', :recurse => true )
  #
  # would have the same result as
  #
  #   Dir.multiglob('**/*')
  #
  #--
  # DEPRECATED
  #
  # Multiglob also accepts '+' and '-' prefixes. Any entry that begins with a '-'
  # is treated as an exclusion glob and will be removed from the final result.
  # For example, to collect all files in the current directory, less ruby scripts:
  #
  #   Dir.multiglob( '*', '-*.rb' )
  #
  # This is very useful in collecting files as specificed by a configuration
  # parameter.
  #++

  def self.multiglob(*patterns)
    options  = (Hash === patterns.last ? patterns.pop : {})

    if options.delete(:recurse)
      #patterns += patterns.collect{ |f| File.join(f, '**', '**') }
      multiglob_r(*patterns)
    end

    bitflags = 0
    bitflags |= File::FNM_NOESCAPE if options[:noescape]
    bitflags |= File::FNM_CASEFOLD if options[:casefold]
    bitflags |= File::FNM_PATHNAME if options[:pathname] or options[:strict]
    bitflags |= File::FNM_DOTMATCH if options[:dotmatch] or options[:strict]

    patterns = [patterns].flatten.compact

    if options[:recurse]
      patterns += patterns.collect{ |f| File.join(f, '**', '**') }
    end

    files = []
    files += patterns.collect{ |pattern| Dir.glob(pattern, bitflags) }.flatten.uniq

    return files
  end

  # The same as +multiglob+, but recusively includes directories.
  #
  #   Dir.multiglob_r( 'folder' )
  #
  # is equivalent to
  #
  #   Dir.multiglob( 'folder', :recurse=>true )
  #
  # The effect of which is
  #
  #   Dir.multiglob( 'folder', 'folder/**/**' )
  #

  def self.multiglob_r(*patterns)
    options = (Hash === patterns.last ? patterns.pop : {})
    matches = multiglob(*patterns)
    directories = matches.select{ |m| File.directory?(m) }
    matches += directories.collect{ |d| multiglob_r(File.join(d, '**'), options) }.flatten
    matches.uniq
    #options = (Hash === patterns.last ? patterns.pop : {})
    #options[:recurse] = true
    #patterns << options
    #multiglob(*patterns)
  end

end
