require 'cli/kit' module CLI module Kit class CommandRegistry attr_reader :commands, :aliases module NullContextualResolver def self.command_names [] end def self.aliases {} end def self.command_class(_name) nil end end def initialize(default:, contextual_resolver: nil) @commands = {} @aliases = {} @default = default @contextual_resolver = contextual_resolver || NullContextualResolver end def resolved_commands @commands.each_with_object({}) do |(k, v), a| a[k] = resolve_class(v) end end def add(const, name) commands[name] = const end def lookup_command(name) name = @default if name.to_s.empty? resolve_command(name) end def add_alias(from, to) aliases[from] = to unless aliases[from] end def command_names @contextual_resolver.command_names + commands.keys end def exist?(name) !resolve_command(name).first.nil? end private def resolve_alias(name) aliases[name] || @contextual_resolver.aliases.fetch(name, name) end def resolve_command(name) name = resolve_alias(name) resolve_global_command(name) || \ resolve_contextual_command(name) || \ [nil, name] end def resolve_global_command(name) klass = resolve_class(commands.fetch(name, nil)) return nil unless klass && klass.defined? [klass, name] rescue NameError nil end def resolve_contextual_command(name) found = @contextual_resolver.command_names.include?(name) return nil unless found [@contextual_resolver.command_class(name), name] end def resolve_class(class_or_proc) if class_or_proc.is_a?(Class) class_or_proc elsif class_or_proc.respond_to?(:call) class_or_proc.call else class_or_proc end end end end end