module Commander # = Manager # # Controls management and invocation of sub-commands. class Manager attr_reader :command_options, :commands, :info attr_reader :user_command, :user_args # Initialize commander singleton. # # == Keys: # # * name (required) # * version (required) # * description # * copyright # # == Examples: # # init_commander( # :name => 'Commander', # :version => Commander::VERSION, # :description => 'Commander utility program.' # ) # def self.instance(options = {}) @@instance ||= Commander::Manager.new options end def self.kill_instance! @@instance = nil end def initialize(options) @info, @command_options = options, {} @user_args = ARGV.dup @info[:help_generator] ||= Commander::HelpGenerators::Default init_version at_exit { run } end def add_command(command) @commands ||= {} and @commands[command.command] = command end def get_command(command) @commands[command.to_sym] end def execute_command abort "Invalid command." if not @user_command unless @user_command.options.empty? opts = OptionParser.new @user_command.options.each { |option| opts.on(*option[:args], &option[:proc]) } opts.parse! @user_args end rescue OptionParser::MissingArgument => e debug_abort e else @user_command.invoke(:when_called_proc, @user_args) end def valid_command?(command) !@commands[command.to_sym].nil? unless command.nil? end alias :include? :valid_command? def empty? @commands.empty? end def length @commands.length end alias :size :length def valid_version?(version) version.split('.').length == 3 if version.is_a? String end def parse_version(version) version.split('.').collect { |v| v.to_i } if version.is_a? String end def debug_abort(msg, exception = nil) abort msg end def init_version raise "Your program must have a version tuple ('x.x.x')." unless valid_version?(@info[:version]) @info[:major], @info[:minor], @info[:tiny] = parse_version(@info[:version]) end def run parse_options! abort "Invalid arguments." if @user_args.empty? @command_options[:help] = true and @user_args.shift if @user_args[0] == 'help' set_user_command case when (@command_options[:help] and @user_args.empty?) then output_help when @command_options[:help] then output_help else execute_command end end def parse_options! opts = OptionParser.new opts.on('--help') { output_help; exit } opts.on('--version') { output_version; exit } opts.parse! @user_args rescue nil end def set_user_command @user_command = get_command(@user_args[0]) unless @user_args.empty? @user_args.shift end def output_help @info[:help_generator].new self end def output_version puts "#{@info[:name]} #{@info[:version]}" end end end