module Sprout module Executable ## # The abstract base class for all Executable parameters. # # This class provides a variety of template methods and general # functionality to the different executable parameter types. # # Many of these parameter attributes are exposed to Sprout::Executable # concrete classes as the options hash like: # # class Foo # include Sprout::Executable # # add_param :name, String, :hidden_name => true # end # # @see Sprout::Executable::Boolean # @see Sprout::Executable::FileParam # @see Sprout::Executable::Files # @see Sprout::Executable::Number # @see Sprout::Executable::ParameterFactory # @see Sprout::Executable::Path # @see Sprout::Executable::Paths # @see Sprout::Executable::StringParam # @see Sprout::Executable::Strings # @see Sprout::Executable::Url # @see Sprout::Executable::Urls # class Param ## # Default value for the delimiter that will # separate parameter names from their values. DEFAULT_DELIMITER = '=' ## # Defaut TYPE assumed for parameters when # creating documentation for the OptionParser. DEFAULT_OPTION_PARSER_TYPE_NAME = 'STRING' ## # Default value for the parameter prefix. # Should usually be pulled from the # +belongs_to+ Sprout::Executable. DEFAULT_PREFIX = '--' ## # Default prefix for truncated parameters. # Should usually be pulled from the # +belongs_to+ Sprout::Executable. DEFAULT_SHORT_PREFIX = '-' ## # The Sprout::Executable that this parameter # instance belongs to. attr_accessor :belongs_to ## # Executable::Params join their name/value pair with an # equals sign by default, this can be modified # To a space or whatever you wish. attr_accessor :delimiter ## # The String description that will be used for # RDoc documentation and user help. attr_accessor :description ## # Boolean value that hides the name parameter # from the shell execution. # # add_param :name, String, :hidden_name => true # # Without this option, the above parameter would # serialize to the process like: # # foo --name=Value # # But with this option, the above parameter would # serialize to the process like: # # foo Value # attr_accessor :hidden_name ## # Boolean value that hides the value parameter # from the shell execution. # # add_param :visible, Boolean, :hidden_value => true # # Without this option, the above parameter would # serialize to the process like: # # foo --visible=true # # But with this option, the above parameter would # serialize to the process like: # # foo --visible # attr_accessor :hidden_value ## # The String (or Symbol) name of the parameter. attr_accessor :name ## # The String prefix that should be in front of each # command line parameter. # # If no value is set for this option, the # DEFAULT_PREFIX (--) will be used for regular parameters, # and the DEFAULT_SHORT_PREFIX (-) will be used for short # parameters. attr_accessor :prefix ## # A Symbol that refers to a method that will return # the expected value when called. This method can be private. # # add_param :visible, Boolean, :reader => :get_visible # # def get_visible # return @visible # end # attr_accessor :reader ## # Boolean value that will cause a Sprout::Errors::UsageError # if the executable is invoked without this parameter first # being set. # # add_param :visible, Boolean :required => true # # Default false # attr_accessor :required ## # An optional Proc that should be called when this parameter # is serialized to shell output. The Proc should return a # String value that makes sense to the underlying process. # # add_param :visible, Boolean, :to_shell_proc => Proc.new {|p| "---result" } # attr_accessor :to_shell_proc ## # The data type of the parameter, used to generate more appropriate # RDoc content for the concrete Sprout::Executable. attr_accessor :type ## # The value that was assigned to this parameter when the # concrete Sprout::Executable was instantiated and configured. attr_accessor :value ## # A Symbol that refers to a method (not accessor) that # will be called when the value is set. This method is # not responsible for actually storing the value, but # should instead be thought of as a badly named callback # that will be triggered with the new value whenever the # value changes. # # This method can be private. # # add_param :visible, Boolean, :writer => :set_visible # # private # # def set_visible value # do_something_with value # value # end # attr_accessor :writer ## # Set the file_expression (blob) to append to each path # in order to build the prerequisites FileList. # # Defaults to the parent Executable.default_file_expression # # TODO: We should add support for file_expressionS # since these are really just blobs that are sent # to the FileList[expr] and that interface accepts # an array. attr_writer :file_expression ## # Optional String value of the name of this parameter # that should be returned to the shell. # # By default, this method will infer the name by # prepending the +prefix+ and replacing underscores # with dashes. For example: # # add_param :some_name, String # # Would return '--some-name=value' to the shell. # # If this option is set, then the provided value # will be used rather than inferred. # # add_param :some_name, String, :shell_name => '--OtherName' # # Would return '--OtherName=value' when sent to the shell. # attr_writer :shell_name ## # Optional String value that should be used for this # parameter's short name. Generally only helpful # for Sprout::Executable 's that are going to be exposed # to Ruby OptionParser as Ruby applications. # # By default, this value will be the first letter # of the parameter name, and when multiple parameters # share the same first letter, the first one encountered # will be used. attr_writer :short_name ## # Default constructor for Params, if you create # a new concrete type, be sure to call +super()+ in your # own constructor. def initialize @description = 'Default Description' @hidden_value = false @hidden_name = false @delimiter = DEFAULT_DELIMITER @option_parser_type_name = DEFAULT_OPTION_PARSER_TYPE_NAME end ## # By default, Executable::Params only appear in the shell # output when they are not nil def visible? !value.nil? end ## # Returns Boolean value if this parameter is required. def required? (required == true) end ## # Ensure this parameter is in a valid state, raise a Sprout::Errors::MissingArgumentError # if it is not. def validate if(required? && value.nil?) raise Sprout::Errors::MissingArgumentError.new("#{name} is required and must not be nil") end end ## # Set the default value of the parameter. # Using this option will ensure that required parameters # are not nil, and default values can be overridden on # instances. # # add_param :name, String, :default => 'Bob' # def default=(value) self.value = value @default = value end ## # Return the default value or nil if none was provided. def default @default end ## # Prepare the parameter for execution or delegation, depending # on what context we're in. def prepare prepare_prerequisites @prepared = true end ## # Returns true if this parameter has already been prepared. def prepared? @prepared end ## # Should the param name be hidden from the shell? # Used for params like 'input' on mxmlc def hidden_name? @hidden_name end ## # Should the param value be hidden from the shell? # Usually used for Boolean toggles like '-debug' def hidden_value? @hidden_value end ## # Leading character for each parameter # Can sometimes be an empty string, # other times it's a double dash '--' # but usually it's just a single dash '-' def prefix @prefix ||= (belongs_to.nil?) ? DEFAULT_PREFIX : belongs_to.default_prefix end def short_prefix @short_prefix ||= (belongs_to.nil?) ? DEFAULT_SHORT_PREFIX : belongs_to.default_short_prefix end ## # How this parameter is provided to the # Ruby OptionParser when being exposed as a Ruby Executable. def option_parser_declaration declaration = default_option_parser_declaration # TODO: Need to figure out how to support hidden name inputs... #if(hidden_name?) #declaration = [option_parser_type_output] # if(!hidden_value?) declaration << delimiter << option_parser_type_output end declaration.join('') end def default_option_parser_declaration [ prefix, option_parser_name ] end ## # The Ruby OptionParser short name with prefix. def option_parser_short_name [ short_prefix, short_name ].join('') end ## # The short name for this parameter. # If it's not explicitly, the first # character of the parameter name will # be used. When multiple parameters have # the same first character, the first one # encountered will win. def short_name @short_name ||= name.to_s.split('').shift end ## # The String representation of the value in # a format that is appropriate for the terminal. # # For certain types of parameters, like File, # spaces may be escaped on some platforms. # def shell_value value.to_s end def file_expression @file_expression ||= belongs_to.default_file_expression end def shell_name @shell_name ||= prefix + name.to_s.split('_').join('-') end ## # Prepare and serialize this parameter to a string # that is appropriate for shell execution on the # current platform. # # Calling +to_shell+ will first trigger a call to # the +prepare+ template method unless +prepared?+ returns +true+. def to_shell prepare if !prepared? validate return '' if !visible? return @to_shell_proc.call(self) unless @to_shell_proc.nil? return shell_value if hidden_name? return shell_name if hidden_value? return [shell_name, delimiter, shell_value].join end # Create a string that can be turned into a file # that rdoc can parse to describe the customized # or generated task using param name, type and # description def to_rdoc result = '' parts = description.split("\n") unless description.nil? result << "# #{parts.join("\n# ")}\n" unless description.nil? result << "def #{name}=(#{type})\n @#{name} = #{type}\nend\n\n" return result end protected def option_parser_name name.to_s.gsub('_', '-') end def option_parser_type_name @option_parser_type_name end def option_parser_type_output type = hidden_value? ? '' : option_parser_type_name required? ? type : "[#{type}]" end def prepare_prerequisites end ## # Clean the provided path using the current Sprout::System. def clean_path path Sprout::System.create.clean_path path end ## # Return true if the Sprout::Executable # that this parameter +belongs_to+ has an +output+ # method (or parameter), and if the provided +file+ # matches the value of that parameter. # # This method (convention) is used to avoid creating circular # prerequisites in Rake. For most types of File parameters # we want to make them into prerequisites, but not if the # File is the one being created by the outer Sprout::Executable. def file_is_output? file belongs_to.respond_to?(:output) && belongs_to.output.to_s == file end end end end