lib/clamp/command.rb in clamp-0.0.9 vs lib/clamp/command.rb in clamp-0.1.0

- old
+ new

@@ -1,55 +1,97 @@ -require 'clamp/command/declaration' require 'clamp/errors' require 'clamp/help' +require 'clamp/option/declaration' require 'clamp/option/parsing' +require 'clamp/parameter/declaration' require 'clamp/parameter/parsing' +require 'clamp/subcommand/declaration' require 'clamp/subcommand/execution' module Clamp + # {Command} models a shell command. Each command invocation is a new object. + # Command options and parameters are represented as attributes + # (see {Command::Declaration}). + # + # The main entry-point is {#run}, which uses {#parse} to populate attributes based + # on an array of command-line arguments, then calls {#execute} (which you provide) + # to make it go. + # class Command - def initialize(name, context = {}) - @name = name + # Create a command execution. + # + # @param [String] invocation_path the path used to invoke the command + # @param [Hash] context additional data the command may need + # + def initialize(invocation_path, context = {}) + @invocation_path = invocation_path @context = context end - attr_reader :name - attr_reader :arguments + # @return [String] the path used to invoke this command + # + attr_reader :invocation_path + + # @return [Array<String>] unconsumed command-line arguments + # + def arguments + @arguments + end - attr_accessor :context - attr_accessor :parent_command - + # Parse command-line arguments. + # + # @param [Array<String>] arguments command-line arguments + # @return [Array<String>] unconsumed arguments + # def parse(arguments) @arguments = arguments.dup parse_options parse_parameters + @arguments end - # default implementation + # Run the command, with the specified arguments. + # + # This calls {#parse} to process the command-line arguments, + # then delegates to {#execute}. + # + # @param [Array<String>] arguments command-line arguments + # + def run(arguments) + parse(arguments) + execute + end + + # Execute the command (assuming that all options/parameters have been set). + # + # This method is designed to be overridden in sub-classes. + # def execute if self.class.has_subcommands? execute_subcommand else raise "you need to define #execute" end end - def run(arguments) - parse(arguments) - execute - end - + # @return [String] usage documentation for this command + # def help - self.class.help(name) + self.class.help(invocation_path) end - include Option::Parsing - include Parameter::Parsing - include Subcommand::Execution + include Clamp::Option::Parsing + include Clamp::Parameter::Parsing + include Clamp::Subcommand::Execution + + protected + attr_accessor :context + attr_accessor :parent_command + private def signal_usage_error(message) e = UsageError.new(message, self) e.set_backtrace(caller) @@ -60,19 +102,27 @@ raise Clamp::HelpWanted.new(self) end class << self - include Command::Declaration + include Clamp::Option::Declaration + include Clamp::Parameter::Declaration + include Clamp::Subcommand::Declaration include Help - def run(name = $0, args = ARGV, context = {}) + # Create an instance of this command class, and run it. + # + # @param [String] invocation_path the path used to invoke the command + # @param [Array<String>] arguments command-line arguments + # @param [Hash] context additional data the command may need + # + def run(invocation_path = $0, arguments = ARGV, context = {}) begin - new(name, context).run(args) + new(invocation_path, context).run(arguments) rescue Clamp::UsageError => e $stderr.puts "ERROR: #{e.message}" $stderr.puts "" - $stderr.puts "See: '#{name} --help'" + $stderr.puts "See: '#{invocation_path} --help'" exit(1) rescue Clamp::HelpWanted => e puts e.command.help end end