class Jets::Commands::Base

def autocomplete(full_command)

If this fails to find a match then return the original full command
def autocomplete(full_command)
  return nil if full_command.nil? # jets help
  eager_load!
  words = full_command.split(':')
  namespace = words[0..-2].join(':') if words.size > 1
  command = words.last
  # Thor's normalize_command_name autocompletes the command but then we need to add the namespace back
  begin
    thor_subclass = klass_from_namespace(namespace) # could NameError
    command = thor_subclass.normalize_command_name(command) # could Thor::AmbiguousCommandError
    [namespace, command].compact.join(':')
  rescue NameError
    full_command # return original full_command
  rescue Thor::AmbiguousCommandError => e
    puts "Unable to autodetect the command name. #{e.message}."
    full_command # return original full_command
  end
end

def banner(command, namespace = nil, subcommand = false)

Use Jets banner instead of Thor to account for namespaces in commands.
def banner(command, namespace = nil, subcommand = false)
  namespace = namespace_from_class(self)
  command_name = command.usage # set with desc when defining tht Thor class
  namespaced_command = [namespace, command_name].compact.join(':')
  "jets #{namespaced_command}"
end

def dispatch(command, given_args, given_opts, config)

required arguments 'project_name' (Thor::RequiredArgumentMissingError)

this error:
Hacky way to handle error for 'jets new' when no project name is passed in to avoid
def dispatch(command, given_args, given_opts, config)
  if given_args.reject{|s| s =~ /^-/} == ['new'] # user forgot to pass a project name
    given_args = ['help', 'new']
  end
  super
end

def eager_load!

We cannot assume we have full access to to the project yet.
There is special eager_load logic here because this is called super early as part of the CLI start.

For help menu to list all commands, we must eager load the command classes.
def eager_load!
  return if Jets::Turbo.afterburner?
  Jets.application.setup_auto_load_paths # in case an app/extension is defined
  Jets::Autoloaders.once.eager_load
end

def help_list(all=false)

def help_list(all=false)
  # hack to show hidden comands when requested
  Thor::HiddenCommand.class_eval do
    def hidden?; false; end
  end if all
  list = []
  eager_load!
  subclasses.each do |klass|
    commands = klass.printable_commands(true, false)
    commands.reject! { |array| array[0].include?(':help') }
    list += commands
  end
  list.sort_by! { |array| array[0] }
end

def hidden?; false; end

def hidden?; false; end

def inherited(base)

def inherited(base)
  super
  if base.name
    self.subclasses << base
  end
end

def klass_from_namespace(namespace)

def klass_from_namespace(namespace)
  if namespace.nil?
    Jets::Commands::Main
  else
    class_name = namespace.gsub(':','/')
    class_name = "Jets::Commands::#{class_name.camelize}"
    class_name.constantize
  end
end

def namespace_from_class(klass)

def namespace_from_class(klass)
  namespace = klass.to_s.sub('Jets::Commands::', '').underscore.gsub('/',':')
  namespace unless namespace == "main"
end

def namespaced_commands

dynamodb:migrate:down
process:controller
build
Fully qualifed task names. Examples:
def namespaced_commands
  eager_load!
  subclasses.map do |klass|
    # This all_tasks is part of Thor not the lambda/dsl.rb
    klass.all_tasks.keys.map do |task_name|
      klass = klass.to_s.sub('Jets::Commands::','')
      namespace = klass =~ /^Main/ ? nil : klass.underscore.gsub('/',':')
      [namespace, task_name].compact.join(':')
    end
  end.flatten.sort
end

def perform(full_command, thor_args)

Same signature as RakeCommand.perform. Not using full_command.

["dynamodb:migrate"]
["help"]
thor_args is an array of commands. Examples:
def perform(full_command, thor_args)
  config = {} # doesnt seem like config is used
  dispatch(nil, thor_args, nil, config)
end

def subclasses

Track all command subclasses.
def subclasses
  @subclasses ||= []
end