kigster/warp-dir

View on GitHub
lib/warp/dir/commander.rb

Summary

Maintainability
A
35 mins
Test Coverage
B
88%
require 'set'
require 'warp/dir/errors'
require 'warp/dir/formatter'
require 'singleton'
module Warp
  module Dir
    class Commander
      include Singleton

      attr_reader :commands
      attr_accessor :command_map

      def initialize
        @commands ||= Set.new # a pre-caution, normally it would already by defined by now
        @command_map   = {}
      end

      def register(command)
        @commands << command if command
        self
      end

      def installed_commands
        @commands.map(&:command_name)
      end

      def lookup(command_name)
        reindex!
        command_map[command_name]
      end

      def find(command_name)
        command = lookup(command_name)
        if command.nil?
          raise ::Warp::Dir::Errors::InvalidCommand.new(command_name)
        end
        command
      end

      def run(command_name, *args)
        cmd = find command_name
        raise ::Warp::Dir::Errors::InvalidCommand.new(command_name) unless cmd.is_a?(warp::Dir::Command)
        cmd.new(*args).run
      end

      def reindex!
        commands.each do |command|
          if command.respond_to?(:aliases)
            command.aliases.each do |an_alias|
              if self.command_map[an_alias] && !self.command_map[an_alias] == command
                raise Warp::Dir::Errors::InvalidCommand.new("Duplicate alias for command #{command}")
              end
              self.command_map[an_alias] = command
            end
          end
          self.command_map[command.command_name] = command
        end
        self
      end

      def validate!
        self.commands.delete_if do |subclass|
          if !subclass.respond_to?(:abstract_class?) && !subclass.method_defined?(:run)
            raise ::Warp::Dir::Errors::InvalidCommand.new(subclass)
          end
          subclass.respond_to?(:abstract_class?) || !subclass.method_defined?(:run)
        end
      end
    end
  end
end