module Rails::Generators

def self.aliases #:nodoc:

:nodoc:
def self.aliases #:nodoc:
  @aliases ||= DEFAULT_ALIASES.dup
end

def self.configure!(config = Rails.application.config.generators) #:nodoc:

:nodoc:
def self.configure!(config = Rails.application.config.generators) #:nodoc:
  no_color! unless config.colorize_logging
  aliases.deep_merge! config.aliases
  options.deep_merge! config.options
  fallbacks.merge! config.fallbacks
  templates_path.concat config.templates
  templates_path.uniq!
end

def self.fallbacks


Rails::Generators.fallbacks[:shoulda] = :test_unit

some of them are not available by adding a fallback:
Shoulda then can tell generators to search for test_unit generators when

test_unit ones.
of test_unit. However, most part of shoulda generators are similar to
For example, shoulda is considered a test_framework and is an extension

they can add a fallback.
generator group to fallback to another group in case of missing generators,
Hold configured generators fallbacks. If a plugin developer wants a
def self.fallbacks
  @fallbacks ||= {}
end

def self.find_by_namespace(name, base=nil, context=nil) #:nodoc:

:nodoc:

Rails looks for is the first and last parts of the namespace.
Notice that "rails:generators:webrat" could be loaded as well, what

"rails:webrat", "webrat:integration", "webrat"

Will search for the following generators:

find_by_namespace :webrat, :rails, :integration

==== Examples

looks in load paths and loads the generator just before it's going to be used.
Generators names must end with "_generator.rb". This is required because Rails

Rails finds namespaces similar to thor, it only adds one rule:
def self.find_by_namespace(name, base=nil, context=nil) #:nodoc:
  lookups = []
  lookups << "#{base}:#{name}"    if base
  lookups << "#{name}:#{context}" if context
  unless base || context
    unless name.to_s.include?(?:)
      lookups << "#{name}:#{name}"
      lookups << "rails:#{name}"
    end
    lookups << "#{name}"
  end
  lookup(lookups)
  namespaces = subclasses.inject({}) do |hash, klass|
    hash[klass.namespace] = klass
    hash
  end
  lookups.each do |namespace|
    klass = namespaces[namespace]
    return klass if klass
  end
  invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name)
end

def self.help(command = 'generate')

Show help message with available generators.
def self.help(command = 'generate')
  lookup!
  namespaces = subclasses.map{ |k| k.namespace }
  namespaces.sort!
  groups = Hash.new { |h,k| h[k] = [] }
  namespaces.each do |namespace|
    base = namespace.split(':').first
    groups[base] << namespace
  end
  puts "Usage: rails #{command} GENERATOR [args] [options]"
  puts
  puts "General options:"
  puts "  -h, [--help]     # Print generator's options and usage"
  puts "  -p, [--pretend]  # Run but do not make any changes"
  puts "  -f, [--force]    # Overwrite files that already exist"
  puts "  -s, [--skip]     # Skip files that already exist"
  puts "  -q, [--quiet]    # Suppress status output"
  puts
  puts "Please choose a generator below."
  puts
  # Print Rails defaults first.
  rails = groups.delete("rails")
  rails.map! { |n| n.sub(/^rails:/, '') }
  rails.delete("app")
  print_list("rails", rails)
  hidden_namespaces.each {|n| groups.delete(n.to_s) }
  groups.sort.each { |b, n| print_list(b, n) }
end

def self.hidden_namespaces

def self.hidden_namespaces
  @hidden_namespaces ||= begin
    orm      = options[:rails][:orm]
    test     = options[:rails][:test_framework]
    template = options[:rails][:template_engine]
    [
      "rails",
      "#{orm}:migration",
      "#{orm}:model",
      "#{orm}:observer",
      "#{orm}:session_migration",
      "#{test}:controller",
      "#{test}:helper",
      "#{test}:integration",
      "#{test}:mailer",
      "#{test}:model",
      "#{test}:observer",
      "#{test}:scaffold",
      "#{test}:view",
      "#{test}:performance",
      "#{test}:plugin",
      "#{template}:controller",
      "#{template}:scaffold",
      "#{template}:mailer"
    ]
  end
end

def self.invoke(namespace, args=ARGV, config={})

commands.
It's used as the default entry point for generate, destroy and update
Receives a namespace, arguments and the behavior to invoke the generator.
def self.invoke(namespace, args=ARGV, config={})
  names = namespace.to_s.split(':')
  if klass = find_by_namespace(names.pop, names.any? && names.join(':'))
    args << "--help" if args.empty? && klass.arguments.any? { |a| a.required? }
    klass.start(args, config)
  else
    puts "Could not find generator #{namespace}."
  end
end

def self.invoke_fallbacks_for(name, base) #:nodoc:

:nodoc:
Try fallbacks for the given base.
def self.invoke_fallbacks_for(name, base) #:nodoc:
  return nil unless base && fallbacks[base.to_sym]
  invoked_fallbacks = []
  Array(fallbacks[base.to_sym]).each do |fallback|
    next if invoked_fallbacks.include?(fallback)
    invoked_fallbacks << fallback
    klass = find_by_namespace(name, fallback)
    return klass if klass
  end
  nil
end

def self.load_generators_from_railties! #:nodoc:

:nodoc:
Allow generators to be loaded from custom paths.
def self.load_generators_from_railties! #:nodoc:
  return if defined?(@generators_from_railties) || Rails.application.nil?
  @generators_from_railties = true
  Rails.application.load_generators
end

def self.lookup(namespaces) #:nodoc:

:nodoc:
in the load path.
Receives namespaces in an array and tries to find matching generators
def self.lookup(namespaces) #:nodoc:
  load_generators_from_railties!
  paths = namespaces_to_paths(namespaces)
  paths.each do |raw_path|
    ["rails/generators", "generators"].each do |base|
      path = "#{base}/#{raw_path}_generator"
      begin
        require path
        return
      rescue LoadError => e
        raise unless e.message =~ /#{Regexp.escape(path)}$/
      rescue NameError => e
        raise unless e.message =~ /Rails::Generator([\s(::)]|$)/
        warn "[WARNING] Could not load generator #{path.inspect} because it's a Rails 2.x generator, which is not supported anymore. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
      rescue Exception => e
        warn "[WARNING] Could not load generator #{path.inspect}. Error: #{e.message}.\n#{e.backtrace.join("\n")}"
      end
    end
  end
end

def self.lookup! #:nodoc:

:nodoc:
This will try to load any generator in the load path to show in help.
def self.lookup! #:nodoc:
  load_generators_from_railties!
  $LOAD_PATH.each do |base|
    Dir[File.join(base, "{rails/generators,generators}", "**", "*_generator.rb")].each do |path|
      begin
        require path
      rescue Exception => e
        # No problem
      end
    end
  end
end

def self.namespaces_to_paths(namespaces) #:nodoc:

:nodoc:
in both: "rails/model/model_generator" and "rails/model_generator".
an extra lookup. For example, "rails:model" should be searched
Convert namespaces to paths by replacing ":" for "/" and adding
def self.namespaces_to_paths(namespaces) #:nodoc:
  paths = []
  namespaces.each do |namespace|
    pieces = namespace.split(":")
    paths << pieces.dup.push(pieces.last).join("/")
    paths << pieces.join("/")
  end
  paths.uniq!
  paths
end

def self.no_color!

Remove the color from output.
def self.no_color!
  Thor::Base.shell = Thor::Shell::Basic
end

def self.options #:nodoc:

:nodoc:
def self.options #:nodoc:
  @options ||= DEFAULT_OPTIONS.dup
end

def self.print_list(base, namespaces) #:nodoc:

:nodoc:
Prints a list of generators.
def self.print_list(base, namespaces) #:nodoc:
  namespaces = namespaces.reject do |n|
    hidden_namespaces.include?(n)
  end
  return if namespaces.empty?
  puts "#{base.camelize}:"
  namespaces.each do |namespace|
    puts("  #{namespace}")
  end
  puts
end

def self.subclasses

Track all generators subclasses.
def self.subclasses
  @subclasses ||= []
end

def self.templates_path

def self.templates_path
  @templates_path ||= []
end

def hide_namespaces(*namespaces)

def hide_namespaces(*namespaces)
  hidden_namespaces.concat(namespaces)
end