Automatic CLI Menu Registration Patter

Just wanted to share an automatic way to register menu items in dry-cli without having to individually register them.

  module CLI
    class Error < StandardError; end

    module Commands      
      extend Dry::CLI::Registry
      MENU = [
        {version: {aliases: ["v", "-v", "--version"]}},
        {start: {}},
        {open: {}},        
        {test: {}},
        {save: {}},
        {submit: {}}        
      ]
  
      MENU.each do |command|
        command_name = command.keys.first
        command_options = command.values.first

        require_relative "cli/commands/#{command_name}"

        register(command_name.to_s, const_get("#{command_name.capitalize}"), aliases: command_options.fetch(:aliases, []))
      end
    end
  end

Just put all your command subclasses in your commands directory and they will automatically register. You could even take the MENU constant out of my code and abstract that to class variables or a class method that this could also call to infer the menu entirely from the presence of command classes. You could do the same for submenus by putting them in folders named after their parent menu.

Happy to document this more and even submit a PR to add this functionality if it’s desired.

Thanks for all the code <3

Avi.NYC

1 Like

I like this better than the documentation shows; however, it still has the same problem in that you must know before hand all the commands that are part of your application. If you are allowing for any kind of plugin capability from third parties that process fails.

What I did was just bring the register command inside of the command class invokation and set it up to associate the command name to the class self and volia! Plugins are supported nicely and all the command junk is encapsulated inside the command’s class.