class Bundler::Thor::Runner

:nodoc: # rubocop:disable ClassLength

def self.banner(command, all = false, subcommand = false)

def self.banner(command, all = false, subcommand = false)
  "thor " + command.formatted_usage(self, all, subcommand)
end

def self.exit_on_failure?

def self.exit_on_failure?
  true
end

def display_commands(namespace, list) #:nodoc:

:nodoc:
def display_commands(namespace, list) #:nodoc:
  list.sort! { |a, b| a[0] <=> b[0] }
  say shell.set_color(namespace, :blue, true)
  say "-" * namespace.size
  print_table(list, :truncate => true)
  say
end

def display_klasses(with_modules = false, show_internal = false, klasses = Bundler::Thor::Base.subclasses)


it shows a table with information extracted from the yaml file.
Display information about the given klasses. If with_module is given,
def display_klasses(with_modules = false, show_internal = false, klasses = Bundler::Thor::Base.subclasses)
  klasses -= [Bundler::Thor, Bundler::Thor::Runner, Bundler::Thor::Group] unless show_internal
  fail Error, "No Bundler::Thor commands available" if klasses.empty?
  show_modules if with_modules && !thor_yaml.empty?
  list = Hash.new { |h, k| h[k] = [] }
  groups = klasses.select { |k| k.ancestors.include?(Bundler::Thor::Group) }
  # Get classes which inherit from Bundler::Thor
  (klasses - groups).each { |k| list[k.namespace.split(":").first] += k.printable_commands(false) }
  # Get classes which inherit from Bundler::Thor::Base
  groups.map! { |k| k.printable_commands(false).first }
  list["root"] = groups
  # Order namespaces with default coming first
  list = list.sort { |a, b| a[0].sub(/^default/, "") <=> b[0].sub(/^default/, "") }
  list.each { |n, commands| display_commands(n, commands) unless commands.empty? }
end

def help(meth = nil)


Override Bundler::Thor#help so it can give information about any class and any method.
def help(meth = nil)
  if meth && !self.respond_to?(meth)
    initialize_thorfiles(meth)
    klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth)
    self.class.handle_no_command_error(command, false) if klass.nil?
    klass.start(["-h", command].compact, :shell => shell)
  else
    super
  end
end

def initialize_thorfiles(relevant_to = nil, skip_lookup = false)


skip_lookup true.
described in thorfiles. This look up can be skipped by supplying
By default, it also traverses the current path until find Bundler::Thor files, as

in the thor_root instead of loading them all.
Load the Bundler::Thorfiles. If relevant_to is supplied, looks for specific files
def initialize_thorfiles(relevant_to = nil, skip_lookup = false)
  thorfiles(relevant_to, skip_lookup).each do |f|
    Bundler::Thor::Util.load_thorfile(f, nil, options[:debug]) unless Bundler::Thor::Base.subclass_files.keys.include?(File.expand_path(f))
  end
end

def install(name) # rubocop:disable MethodLength

rubocop:disable MethodLength
def install(name) # rubocop:disable MethodLength
  initialize_thorfiles
  # If a directory name is provided as the argument, look for a 'main.thor'
  # command in said directory.
  begin
    if File.directory?(File.expand_path(name))
      base, package = File.join(name, "main.thor"), :directory
      contents      = open(base) { |input| input.read }
    else
      base, package = name, :file
      contents      = open(name) { |input| input.read }
    end
  rescue OpenURI::HTTPError
    raise Error, "Error opening URI '#{name}'"
  rescue Errno::ENOENT
    fail Error, "Error opening file '#{name}'"
  end
  say "Your Bundler::Thorfile contains:"
  say contents
  unless options["force"]
    return false if no?("Do you wish to continue [y/N]?")
  end
  as = options["as"] || begin
    first_line = contents.split("\n")[0]
    (match = first_line.match(/\s*#\s*module:\s*([^\n]*)/)) ? match[1].strip : nil
  end
  unless as
    basename = File.basename(name)
    as = ask("Please specify a name for #{name} in the system repository [#{basename}]:")
    as = basename if as.empty?
  end
  location = if options[:relative] || name =~ %r{^https?://}
    name
  else
    File.expand_path(name)
  end
  thor_yaml[as] = {
    :filename   => Digest::MD5.hexdigest(name + as),
    :location   => location,
    :namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base)
  }
  save_yaml(thor_yaml)
  say "Storing thor file in your system repository"
  destination = File.join(thor_root, thor_yaml[as][:filename])
  if package == :file
    File.open(destination, "w") { |f| f.puts contents }
  else
    FileUtils.cp_r(name, destination)
  end
  thor_yaml[as][:filename] # Indicate success
end

def installed

def installed
  initialize_thorfiles(nil, true)
  display_klasses(true, options["internal"])
end

def list(search = "")

def list(search = "")
  initialize_thorfiles
  search = ".*#{search}" if options["substring"]
  search = /^#{search}.*/i
  group  = options[:group] || "standard"
  klasses = Bundler::Thor::Base.subclasses.select do |k|
    (options[:all] || k.group == group) && k.namespace =~ search
  end
  display_klasses(false, false, klasses)
end

def method_missing(meth, *args)


Bundler::Thor::Runner is then responsible for finding the command in all classes.
If a command is not found on Bundler::Thor::Runner, method missing is invoked and
def method_missing(meth, *args)
  meth = meth.to_s
  initialize_thorfiles(meth)
  klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth)
  self.class.handle_no_command_error(command, false) if klass.nil?
  args.unshift(command) if command
  klass.start(args, :shell => shell)
end

def save_yaml(yaml)


Save the yaml file. If none exists in thor root, creates one.
def save_yaml(yaml)
  yaml_file = File.join(thor_root, "thor.yml")
  unless File.exist?(yaml_file)
    FileUtils.mkdir_p(thor_root)
    yaml_file = File.join(thor_root, "thor.yml")
    FileUtils.touch(yaml_file)
  end
  File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
end

def show_modules #:nodoc:

:nodoc:
def show_modules #:nodoc:
  info  = []
  labels = %w[Modules Namespaces]
  info << labels
  info << ["-" * labels[0].size, "-" * labels[1].size]
  thor_yaml.each do |name, hash|
    info << [name, hash[:namespaces].join(", ")]
  end
  print_table info
  say ""
end

def thor_root

def thor_root
  Bundler::Thor::Util.thor_root
end

def thor_yaml

def thor_yaml
  @thor_yaml ||= begin
    yaml_file = File.join(thor_root, "thor.yml")
    yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file)
    yaml || {}
  end
end

def thorfiles(relevant_to = nil, skip_lookup = false)


5. c:\ <-- no Bundler::Thorfiles found!
4. c:\Documents and Settings
3. c:\Documents and Settings\james
2. c:\Documents and Settings\james\dev
1. c:\Documents and Settings\james\dev\thor

Suppose we start at c:\Documents and Settings\james\dev\thor ...

3. /Users/wycats <-- we find a Bundler::Thorfile here, so we stop
2. /Users/wycats/dev
1. /Users/wycats/dev/thor

If we start at /Users/wycats/dev/thor ...

==== Example

Bundler::Thorfiles can override them.
We also ensure that system-wide Bundler::Thorfiles are loaded first, so local

directory of your system. If at any time we find a Bundler::Thor file, we stop.
Finds Bundler::Thorfiles by traversing from your current directory down to the root
def thorfiles(relevant_to = nil, skip_lookup = false)
  thorfiles = []
  unless skip_lookup
    Pathname.pwd.ascend do |path|
      thorfiles = Bundler::Thor::Util.globs_for(path).map { |g| Dir[g] }.flatten
      break unless thorfiles.empty?
    end
  end
  files  = (relevant_to ? thorfiles_relevant_to(relevant_to) : Bundler::Thor::Util.thor_root_glob)
  files += thorfiles
  files -= ["#{thor_root}/thor.yml"]
  files.map! do |file|
    File.directory?(file) ? File.join(file, "main.thor") : file
  end
end

def thorfiles_relevant_to(meth)


namespaces registered.
will load all thor files in the thor.yaml that has "foo" e "foo:bar"
Load Bundler::Thorfiles relevant to the given method. If you provide "foo:bar" it
def thorfiles_relevant_to(meth)
  lookup = [meth, meth.split(":")[0...-1].join(":")]
  files = thor_yaml.select do |k, v|
    v[:namespaces] && !(v[:namespaces] & lookup).empty?
  end
  files.map { |k, v| File.join(thor_root, "#{v[:filename]}") }
end

def uninstall(name)

def uninstall(name)
  fail Error, "Can't find module '#{name}'" unless thor_yaml[name]
  say "Uninstalling #{name}."
  FileUtils.rm_rf(File.join(thor_root, "#{thor_yaml[name][:filename]}"))
  thor_yaml.delete(name)
  save_yaml(thor_yaml)
  puts "Done."
end

def update(name)

def update(name)
  fail Error, "Can't find module '#{name}'" if !thor_yaml[name] || !thor_yaml[name][:location]
  say "Updating '#{name}' from #{thor_yaml[name][:location]}"
  old_filename = thor_yaml[name][:filename]
  self.options = options.merge("as" => name)
  if File.directory? File.expand_path(name)
    FileUtils.rm_rf(File.join(thor_root, old_filename))
    thor_yaml.delete(old_filename)
    save_yaml(thor_yaml)
    filename = install(name)
  else
    filename = install(thor_yaml[name][:location])
  end
  unless filename == old_filename
    File.delete(File.join(thor_root, old_filename))
  end
end

def version

def version
  require "bundler/vendor/thor/lib/thor/version"
  say "Bundler::Thor #{Bundler::Thor::VERSION}"
end