require 'miu' module Miu module Plugin def self.included(base) base.extend ClassMethods base.called_from = begin call_stack = caller.map { |p| p.sub(/:\d+.*/, '') } File.dirname(call_stack.detect { |p| p !~ %r(miu[\w.-]*/lib/miu/plugins) }) end end module ClassMethods attr_accessor :called_from def register(*args, &block) require 'miu/cli' options = args.last.is_a?(::Hash) ? args.pop : {} name = args.shift plugin = args.shift || self usage = options[:usage] || "#{name} [COMMAND]" desc = options[:desc] || plugin.to_s Miu.plugins[name] = plugin Miu::CLI.register generate_subcommand(name, plugin, &block), name, usage, desc if block end private def generate_subcommand(name, plugin, &block) require 'thor' Class.new ::Thor do include ::Thor::Actions add_runtime_options! class << self def source_root Miu.find_root('Gemfile', plugin.called_from) end def destination_root Miu.root end def banner(task, namespace = nil, subcommand = true) super end end namespace name class_eval &block if block end end end end end