class ChefCLI::CommandsMap


end
c.builtin(“documented-cmd”, :DocumentedCmd, desc: “A short description”)
# You can add a description that will show up in ‘chef -h` output (recommended):
c.builtin(“weird-command”, :WeirdoClass, require_path: “chef-cli/command/this_is_cray”)
# Set the require path explicitly:
c.builtin(“my-command”, :MyCommand)
# The “require path” is inferred to be “chef-cli/command/my_command”
# assigns `chef my-command` to the class ChefCLI::Command::MyCommand.
ChefCLI.commands do |c|
ChefCLI.commands, like so:
You can configure a multiple commands at once in a block using
A “singleton-ish” instance of this class is stored as ChefCLI.commands_map.
## Adding new commands globally:
4. It’s not actually that much work to maintain the mapping.
their own complications and tradeoffs and don’t fully solve the problem.
3. Other ways to mitigate the performance issue (loading deps lazily) have
commands, which is actually a common thing to do.
command name, but then you have to do a lot of work to list all of the
2. You can workaround the above by having a convention mapping filename to
slow, and CLI apps need to be fast.
code, including dependencies that are installed by rubygems, etc. This gets
1. Performance. As the CLI suite grows, you have to load more and more
decided against it here:
and metaprogramming. We’ve implemented this approach in the past and
In ruby it’s more typical to handle this sort of thing using conventions
those commands are defined and the classes that implement the commands.
CommandsMap maintains a mapping of subcommand names to the files where

def builtin(name, constant_name, require_path: NULL_ARG, desc: "", hidden: false)

def builtin(name, constant_name, require_path: NULL_ARG, desc: "", hidden: false)
  if null?(require_path)
    snake_case_path = name.tr("-", "_")
    require_path = "chef-cli/command/#{snake_case_path}"
  end
  command_specs[name] = CommandSpec.new(name, constant_name, require_path, desc, hidden)
end

def command_names

def command_names
  command_specs.keys
end

def have_command?(name)

def have_command?(name)
  command_specs.key?(name)
end

def initialize

def initialize
  @command_specs = {}
end

def instantiate(name)

def instantiate(name)
  spec_for(name).instantiate
end

def null?(argument)

def null?(argument)
  argument.equal?(NULL_ARG)
end

def spec_for(name)

def spec_for(name)
  command_specs[name]
end