configurable 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History +9 -0
 - data/lib/config_parser.rb +2 -3
 - data/lib/config_parser/utils.rb +4 -8
 - data/lib/configurable.rb +34 -0
 - data/lib/configurable/delegate.rb +23 -10
 - data/lib/configurable/validation.rb +197 -30
 - metadata +2 -2
 
    
        data/History
    CHANGED
    
    | 
         @@ -1,3 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            == 0.4.2 / 2009-03-30
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * set delegate default no longer freezes value
         
     | 
| 
      
 4 
     | 
    
         
            +
            * added :duplicate_default attribute to turn off default
         
     | 
| 
      
 5 
     | 
    
         
            +
              value duplication
         
     | 
| 
      
 6 
     | 
    
         
            +
            * standardized formatting of argument names
         
     | 
| 
      
 7 
     | 
    
         
            +
            * added select and list_select validations
         
     | 
| 
      
 8 
     | 
    
         
            +
            * added io validation + open_io method
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
       1 
10 
     | 
    
         
             
            == 0.4.1 / 2009-03-23
         
     | 
| 
       2 
11 
     | 
    
         | 
| 
       3 
12 
     | 
    
         
             
            * Simplified internal API for nesting (removed initialize_<key>)
         
     | 
    
        data/lib/config_parser.rb
    CHANGED
    
    | 
         @@ -346,14 +346,13 @@ class ConfigParser 
     | 
|
| 
       346 
346 
     | 
    
         
             
                block = case attributes[:type]
         
     | 
| 
       347 
347 
     | 
    
         
             
                when :switch then setup_switch(key, default_value, attributes)
         
     | 
| 
       348 
348 
     | 
    
         
             
                when :flag   then setup_flag(key, default_value, attributes)
         
     | 
| 
       349 
     | 
    
         
            -
                when :list 
     | 
| 
      
 349 
     | 
    
         
            +
                when :list, :list_select then setup_list(key, attributes)
         
     | 
| 
       350 
350 
     | 
    
         
             
                when :hidden then return nil
         
     | 
| 
       351 
     | 
    
         
            -
                when nil     then setup_option(key, attributes)
         
     | 
| 
       352 
351 
     | 
    
         
             
                else
         
     | 
| 
       353 
352 
     | 
    
         
             
                  if respond_to?("setup_#{attributes[:type]}")
         
     | 
| 
       354 
353 
     | 
    
         
             
                    send("setup_#{attributes[:type]}", key, default_value, attributes)
         
     | 
| 
       355 
354 
     | 
    
         
             
                  else
         
     | 
| 
       356 
     | 
    
         
            -
                     
     | 
| 
      
 355 
     | 
    
         
            +
                    setup_option(key, attributes)
         
     | 
| 
       357 
356 
     | 
    
         
             
                  end
         
     | 
| 
       358 
357 
     | 
    
         
             
                end
         
     | 
| 
       359 
358 
     | 
    
         | 
    
        data/lib/config_parser/utils.rb
    CHANGED
    
    | 
         @@ -120,19 +120,15 @@ class ConfigParser 
     | 
|
| 
       120 
120 
     | 
    
         
             
                # Attributes:
         
     | 
| 
       121 
121 
     | 
    
         
             
                #
         
     | 
| 
       122 
122 
     | 
    
         
             
                #   :long      the long key ("--key")
         
     | 
| 
       123 
     | 
    
         
            -
                #   :arg_name  the argument name ("KEY" 
     | 
| 
      
 123 
     | 
    
         
            +
                #   :arg_name  the argument name ("KEY")
         
     | 
| 
       124 
124 
     | 
    
         
             
                #   :split     the split character
         
     | 
| 
       125 
125 
     | 
    
         
             
                #
         
     | 
| 
       126 
126 
     | 
    
         
             
                def setup_list(key, attributes={})
         
     | 
| 
       127 
127 
     | 
    
         
             
                  attributes[:long] ||= "--#{key}"
         
     | 
| 
      
 128 
     | 
    
         
            +
                  attributes[:long].to_s =~ /^(--)?(.*)$/ 
         
     | 
| 
      
 129 
     | 
    
         
            +
                  attributes[:arg_name] ||= $2.upcase
         
     | 
| 
       128 
130 
     | 
    
         | 
| 
       129 
     | 
    
         
            -
                   
     | 
| 
       130 
     | 
    
         
            -
                    attributes[:arg_name] ||= %w{A B C}.join(split)
         
     | 
| 
       131 
     | 
    
         
            -
                  else
         
     | 
| 
       132 
     | 
    
         
            -
                    attributes[:long].to_s =~ /^(--)?(.*)$/ 
         
     | 
| 
       133 
     | 
    
         
            -
                    attributes[:arg_name] ||= $2.upcase
         
     | 
| 
       134 
     | 
    
         
            -
                  end
         
     | 
| 
       135 
     | 
    
         
            -
                  
         
     | 
| 
      
 131 
     | 
    
         
            +
                  split = attributes[:split]
         
     | 
| 
       136 
132 
     | 
    
         
             
                  n = attributes[:n]
         
     | 
| 
       137 
133 
     | 
    
         | 
| 
       138 
134 
     | 
    
         
             
                  lambda do |value|
         
     | 
    
        data/lib/configurable.rb
    CHANGED
    
    | 
         @@ -173,6 +173,40 @@ module Configurable 
     | 
|
| 
       173 
173 
     | 
    
         
             
              end
         
     | 
| 
       174 
174 
     | 
    
         | 
| 
       175 
175 
     | 
    
         
             
              protected
         
     | 
| 
      
 176 
     | 
    
         
            +
              
         
     | 
| 
      
 177 
     | 
    
         
            +
              # Opens the file specified by io and yield it to the block.  If io is an
         
     | 
| 
      
 178 
     | 
    
         
            +
              # IO, it will be yielded immediately, and the mode is ignored.  Nil io are
         
     | 
| 
      
 179 
     | 
    
         
            +
              # simply ignored.  The input io is always returned.
         
     | 
| 
      
 180 
     | 
    
         
            +
              #
         
     | 
| 
      
 181 
     | 
    
         
            +
              # === Usage
         
     | 
| 
      
 182 
     | 
    
         
            +
              #
         
     | 
| 
      
 183 
     | 
    
         
            +
              # open_io is used to compliment the io validation, to ensure that if a file
         
     | 
| 
      
 184 
     | 
    
         
            +
              # is specified, it will be closed.
         
     | 
| 
      
 185 
     | 
    
         
            +
              #
         
     | 
| 
      
 186 
     | 
    
         
            +
              #   class IoSample
         
     | 
| 
      
 187 
     | 
    
         
            +
              #     include Configurable
         
     | 
| 
      
 188 
     | 
    
         
            +
              #     config :output, $stdout, &c.io    # can be an io or filepath
         
     | 
| 
      
 189 
     | 
    
         
            +
              #
         
     | 
| 
      
 190 
     | 
    
         
            +
              #     def say_hello
         
     | 
| 
      
 191 
     | 
    
         
            +
              #       open_io(output, 'w') do |io|
         
     | 
| 
      
 192 
     | 
    
         
            +
              #         io << 'hello!'
         
     | 
| 
      
 193 
     | 
    
         
            +
              #       end
         
     | 
| 
      
 194 
     | 
    
         
            +
              #     end
         
     | 
| 
      
 195 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 196 
     | 
    
         
            +
              #
         
     | 
| 
      
 197 
     | 
    
         
            +
              # In short, this method provides a way to responsibly handle IO and file
         
     | 
| 
      
 198 
     | 
    
         
            +
              # configurations. 
         
     | 
| 
      
 199 
     | 
    
         
            +
              def open_io(io, mode='r')
         
     | 
| 
      
 200 
     | 
    
         
            +
                case io
         
     | 
| 
      
 201 
     | 
    
         
            +
                when String
         
     | 
| 
      
 202 
     | 
    
         
            +
                  dir = File.dirname(io)
         
     | 
| 
      
 203 
     | 
    
         
            +
                  FileUtils.mkdir_p(dir) unless File.directory?(dir)
         
     | 
| 
      
 204 
     | 
    
         
            +
                  File.open(io, mode) {|file| yield(file) }
         
     | 
| 
      
 205 
     | 
    
         
            +
                when nil
         
     | 
| 
      
 206 
     | 
    
         
            +
                else yield(io)
         
     | 
| 
      
 207 
     | 
    
         
            +
                end
         
     | 
| 
      
 208 
     | 
    
         
            +
                io
         
     | 
| 
      
 209 
     | 
    
         
            +
              end
         
     | 
| 
       176 
210 
     | 
    
         | 
| 
       177 
211 
     | 
    
         
             
              # Initializes config. Default config values 
         
     | 
| 
       178 
212 
     | 
    
         
             
              # are overridden as specified by overrides.
         
     | 
| 
         @@ -22,23 +22,25 @@ module Configurable 
     | 
|
| 
       22 
22 
     | 
    
         
             
                # The writer method, by default key=
         
     | 
| 
       23 
23 
     | 
    
         
             
                attr_reader :writer
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                # An hash of metadata for self, used to present the 
         
     | 
| 
       26 
     | 
    
         
            -
                #  
     | 
| 
       27 
     | 
    
         
            -
                #  
     | 
| 
      
 25 
     | 
    
         
            +
                # An hash of metadata for self, used to present the delegate in different
         
     | 
| 
      
 26 
     | 
    
         
            +
                # contexts (ex on the command line, in a web form, or a desktop app).
         
     | 
| 
      
 27 
     | 
    
         
            +
                # Note that attributes should be set through []= and not through this
         
     | 
| 
      
 28 
     | 
    
         
            +
                # reader.
         
     | 
| 
       28 
29 
     | 
    
         
             
                attr_reader :attributes
         
     | 
| 
       29 
30 
     | 
    
         | 
| 
       30 
31 
     | 
    
         
             
                # Initializes a new Delegate with the specified key and default value.
         
     | 
| 
       31 
32 
     | 
    
         
             
                def initialize(reader, writer="#{reader}=", default=nil, attributes={})
         
     | 
| 
      
 33 
     | 
    
         
            +
                  @attributes = attributes
         
     | 
| 
      
 34 
     | 
    
         
            +
                  
         
     | 
| 
       32 
35 
     | 
    
         
             
                  self.default = default
         
     | 
| 
       33 
36 
     | 
    
         
             
                  self.reader = reader
         
     | 
| 
       34 
37 
     | 
    
         
             
                  self.writer = writer
         
     | 
| 
       35 
     | 
    
         
            -
              
         
     | 
| 
       36 
     | 
    
         
            -
                  @attributes = attributes
         
     | 
| 
       37 
38 
     | 
    
         
             
                end
         
     | 
| 
       38 
39 
     | 
    
         | 
| 
       39 
40 
     | 
    
         
             
                # Sets the value of an attribute.
         
     | 
| 
       40 
41 
     | 
    
         
             
                def []=(key, value)
         
     | 
| 
       41 
42 
     | 
    
         
             
                  attributes[key] = value
         
     | 
| 
      
 43 
     | 
    
         
            +
                  reset_duplicable if key == :duplicate_default
         
     | 
| 
       42 
44 
     | 
    
         
             
                end
         
     | 
| 
       43 
45 
     | 
    
         | 
| 
       44 
46 
     | 
    
         
             
                # Returns the value for the specified attribute, or
         
     | 
| 
         @@ -49,13 +51,14 @@ module Configurable 
     | 
|
| 
       49 
51 
     | 
    
         | 
| 
       50 
52 
     | 
    
         
             
                # Sets the default value for self.
         
     | 
| 
       51 
53 
     | 
    
         
             
                def default=(value)
         
     | 
| 
       52 
     | 
    
         
            -
                  @ 
     | 
| 
       53 
     | 
    
         
            -
                   
     | 
| 
      
 54 
     | 
    
         
            +
                  @default = value
         
     | 
| 
      
 55 
     | 
    
         
            +
                  reset_duplicable
         
     | 
| 
       54 
56 
     | 
    
         
             
                end
         
     | 
| 
       55 
57 
     | 
    
         | 
| 
       56 
     | 
    
         
            -
                # Returns the default value, or a duplicate of the default
         
     | 
| 
       57 
     | 
    
         
            -
                # value  
     | 
| 
       58 
     | 
    
         
            -
                #  
     | 
| 
      
 58 
     | 
    
         
            +
                # Returns the default value, or a duplicate of the default value if specified.
         
     | 
| 
      
 59 
     | 
    
         
            +
                # The default value will not be duplicated unless duplicable (see 
         
     | 
| 
      
 60 
     | 
    
         
            +
                # Delegate.duplicable_value?).  Duplication can also be turned off by
         
     | 
| 
      
 61 
     | 
    
         
            +
                # specifying self[:duplicate_default] = false.
         
     | 
| 
       59 
62 
     | 
    
         
             
                def default(duplicate=true)
         
     | 
| 
       60 
63 
     | 
    
         
             
                  duplicate && @duplicable ? @default.dup : @default
         
     | 
| 
       61 
64 
     | 
    
         
             
                end
         
     | 
| 
         @@ -86,5 +89,15 @@ module Configurable 
     | 
|
| 
       86 
89 
     | 
    
         
             
                  self.writer == another.writer &&
         
     | 
| 
       87 
90 
     | 
    
         
             
                  self.default(false) == another.default(false)
         
     | 
| 
       88 
91 
     | 
    
         
             
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
                
         
     | 
| 
      
 93 
     | 
    
         
            +
                private
         
     | 
| 
      
 94 
     | 
    
         
            +
                
         
     | 
| 
      
 95 
     | 
    
         
            +
                # resets marker indiciating whether or not a default value is duplicable
         
     | 
| 
      
 96 
     | 
    
         
            +
                def reset_duplicable # :nodoc:
         
     | 
| 
      
 97 
     | 
    
         
            +
                  @duplicable = case attributes[:duplicate_default]
         
     | 
| 
      
 98 
     | 
    
         
            +
                  when true, nil then Delegate.duplicable_value?(@default)
         
     | 
| 
      
 99 
     | 
    
         
            +
                  else false
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
       89 
102 
     | 
    
         
             
              end
         
     | 
| 
       90 
103 
     | 
    
         
             
            end
         
     | 
| 
         @@ -46,6 +46,14 @@ module Configurable 
     | 
|
| 
       46 
46 
     | 
    
         
             
                # in Configurable::DEFAULT_ATTRIBUTES.
         
     | 
| 
       47 
47 
     | 
    
         
             
                def register(block, attributes)
         
     | 
| 
       48 
48 
     | 
    
         
             
                  DEFAULT_ATTRIBUTES[block] = attributes
         
     | 
| 
      
 49 
     | 
    
         
            +
                  block
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
                
         
     | 
| 
      
 52 
     | 
    
         
            +
                # Registers the default attributes of the source as the attributes
         
     | 
| 
      
 53 
     | 
    
         
            +
                # of the target.  Attributes are duplicated so they may be modifed.
         
     | 
| 
      
 54 
     | 
    
         
            +
                def register_as(source, target)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  DEFAULT_ATTRIBUTES[target] = DEFAULT_ATTRIBUTES[source].dup
         
     | 
| 
      
 56 
     | 
    
         
            +
                  target
         
     | 
| 
       49 
57 
     | 
    
         
             
                end
         
     | 
| 
       50 
58 
     | 
    
         | 
| 
       51 
59 
     | 
    
         
             
                # Returns input if it matches any of the validations as in would in a case
         
     | 
| 
         @@ -71,9 +79,9 @@ module Configurable 
     | 
|
| 
       71 
79 
     | 
    
         
             
                    case input
         
     | 
| 
       72 
80 
     | 
    
         
             
                    when *validations then input
         
     | 
| 
       73 
81 
     | 
    
         
             
                    else 
         
     | 
| 
       74 
     | 
    
         
            -
                      if block_given? 
         
     | 
| 
       75 
     | 
    
         
            -
                         
     | 
| 
       76 
     | 
    
         
            -
                      else 
     | 
| 
      
 82 
     | 
    
         
            +
                      if block_given? && yield(input)
         
     | 
| 
      
 83 
     | 
    
         
            +
                        input
         
     | 
| 
      
 84 
     | 
    
         
            +
                      else
         
     | 
| 
       77 
85 
     | 
    
         
             
                        raise ValidationError.new(input, validations)
         
     | 
| 
       78 
86 
     | 
    
         
             
                      end
         
     | 
| 
       79 
87 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -82,7 +90,21 @@ module Configurable 
     | 
|
| 
       82 
90 
     | 
    
         
             
                  else raise ArgumentError, "validations must be nil, or an array of valid inputs"
         
     | 
| 
       83 
91 
     | 
    
         
             
                  end
         
     | 
| 
       84 
92 
     | 
    
         
             
                end
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
      
 93 
     | 
    
         
            +
                
         
     | 
| 
      
 94 
     | 
    
         
            +
                # Helper to load the input into a valid object.  If a valid object is not
         
     | 
| 
      
 95 
     | 
    
         
            +
                # loaded as YAML, or if an error occurs, the original input is returned.
         
     | 
| 
      
 96 
     | 
    
         
            +
                def load_if_yaml(input, *validations)
         
     | 
| 
      
 97 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 98 
     | 
    
         
            +
                    yaml = YAML.load(input)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    case yaml
         
     | 
| 
      
 100 
     | 
    
         
            +
                    when *validations then yaml
         
     | 
| 
      
 101 
     | 
    
         
            +
                    else input
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
                  rescue(ArgumentError)
         
     | 
| 
      
 104 
     | 
    
         
            +
                    input
         
     | 
| 
      
 105 
     | 
    
         
            +
                  end
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
                
         
     | 
| 
       86 
108 
     | 
    
         
             
                # Returns a block that calls validate using the block input
         
     | 
| 
       87 
109 
     | 
    
         
             
                # and validations.
         
     | 
| 
       88 
110 
     | 
    
         
             
                def check(*validations)
         
     | 
| 
         @@ -127,8 +149,11 @@ module Configurable 
     | 
|
| 
       127 
149 
     | 
    
         
             
                  input = validate(input, [String])
         
     | 
| 
       128 
150 
     | 
    
         
             
                  eval %Q{"#{input}"}
         
     | 
| 
       129 
151 
     | 
    
         
             
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
                
         
     | 
| 
      
 153 
     | 
    
         
            +
                # default attributes {:type => :string, :example => "string"}
         
     | 
| 
       130 
154 
     | 
    
         
             
                STRING = string_validation_block
         
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
      
 155 
     | 
    
         
            +
                register STRING, :type => :string, :example => "string"
         
     | 
| 
      
 156 
     | 
    
         
            +
                
         
     | 
| 
       132 
157 
     | 
    
         
             
                # Same as string but allows nil.  Note the special
         
     | 
| 
       133 
158 
     | 
    
         
             
                # behavior of the nil string '~' -- rather than
         
     | 
| 
       134 
159 
     | 
    
         
             
                # being treated as a string, it is processed as nil
         
     | 
| 
         @@ -145,8 +170,10 @@ module Configurable 
     | 
|
| 
       145 
170 
     | 
    
         
             
                  else eval %Q{"#{input}"}
         
     | 
| 
       146 
171 
     | 
    
         
             
                  end
         
     | 
| 
       147 
172 
     | 
    
         
             
                end
         
     | 
| 
      
 173 
     | 
    
         
            +
                
         
     | 
| 
       148 
174 
     | 
    
         
             
                STRING_OR_NIL = string_or_nil_validation_block
         
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
      
 175 
     | 
    
         
            +
                register_as STRING, STRING_OR_NIL
         
     | 
| 
      
 176 
     | 
    
         
            +
                
         
     | 
| 
       150 
177 
     | 
    
         
             
                # Returns a block that checks the input is a symbol.
         
     | 
| 
       151 
178 
     | 
    
         
             
                # String inputs are loaded as yaml first.
         
     | 
| 
       152 
179 
     | 
    
         
             
                #
         
     | 
| 
         @@ -157,15 +184,20 @@ module Configurable 
     | 
|
| 
       157 
184 
     | 
    
         
             
                #   symbol.call('str')        # => ValidationError
         
     | 
| 
       158 
185 
     | 
    
         
             
                #
         
     | 
| 
       159 
186 
     | 
    
         
             
                def symbol(); SYMBOL; end
         
     | 
| 
      
 187 
     | 
    
         
            +
                
         
     | 
| 
      
 188 
     | 
    
         
            +
                # default attributes {:type => :symbol, :example => ":sym"}
         
     | 
| 
       160 
189 
     | 
    
         
             
                SYMBOL = yaml(Symbol)
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
      
 190 
     | 
    
         
            +
                register SYMBOL, :type => :symbol, :example => ":sym"
         
     | 
| 
      
 191 
     | 
    
         
            +
                
         
     | 
| 
       162 
192 
     | 
    
         
             
                # Same as symbol but allows nil:
         
     | 
| 
       163 
193 
     | 
    
         
             
                #
         
     | 
| 
       164 
194 
     | 
    
         
             
                #   symbol_or_nil.call('~')   # => nil
         
     | 
| 
       165 
195 
     | 
    
         
             
                #   symbol_or_nil.call(nil)   # => nil
         
     | 
| 
       166 
196 
     | 
    
         
             
                def symbol_or_nil(); SYMBOL_OR_NIL; end
         
     | 
| 
      
 197 
     | 
    
         
            +
                
         
     | 
| 
       167 
198 
     | 
    
         
             
                SYMBOL_OR_NIL = yaml(Symbol, nil)
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
      
 199 
     | 
    
         
            +
                register_as SYMBOL, SYMBOL_OR_NIL
         
     | 
| 
      
 200 
     | 
    
         
            +
                
         
     | 
| 
       169 
201 
     | 
    
         
             
                # Returns a block that checks the input is true, false or nil.
         
     | 
| 
       170 
202 
     | 
    
         
             
                # String inputs are loaded as yaml first.
         
     | 
| 
       171 
203 
     | 
    
         
             
                #
         
     | 
| 
         @@ -182,7 +214,10 @@ module Configurable 
     | 
|
| 
       182 
214 
     | 
    
         
             
                #   boolean.call("str")       # => ValidationError
         
     | 
| 
       183 
215 
     | 
    
         
             
                #
         
     | 
| 
       184 
216 
     | 
    
         
             
                def boolean(); BOOLEAN; end
         
     | 
| 
      
 217 
     | 
    
         
            +
                
         
     | 
| 
      
 218 
     | 
    
         
            +
                # default attributes {:type => :boolean, :example => "true, yes"}
         
     | 
| 
       185 
219 
     | 
    
         
             
                BOOLEAN = yaml(true, false, nil)
         
     | 
| 
      
 220 
     | 
    
         
            +
                register BOOLEAN, :type => :boolean, :example => "true, yes"
         
     | 
| 
       186 
221 
     | 
    
         | 
| 
       187 
222 
     | 
    
         
             
                # Same as boolean.
         
     | 
| 
       188 
223 
     | 
    
         
             
                def switch(); SWITCH; end
         
     | 
| 
         @@ -209,9 +244,9 @@ module Configurable 
     | 
|
| 
       209 
244 
     | 
    
         
             
                #
         
     | 
| 
       210 
245 
     | 
    
         
             
                def array(); ARRAY; end
         
     | 
| 
       211 
246 
     | 
    
         | 
| 
       212 
     | 
    
         
            -
                # default attributes {: 
     | 
| 
      
 247 
     | 
    
         
            +
                # default attributes {:type => :array, :example => "[a, b, c]"}
         
     | 
| 
       213 
248 
     | 
    
         
             
                ARRAY = yaml(Array)
         
     | 
| 
       214 
     | 
    
         
            -
                register ARRAY, : 
     | 
| 
      
 249 
     | 
    
         
            +
                register ARRAY, :type => :array, :example => "[a, b, c]"
         
     | 
| 
       215 
250 
     | 
    
         | 
| 
       216 
251 
     | 
    
         
             
                # Same as array but allows nil:
         
     | 
| 
       217 
252 
     | 
    
         
             
                #
         
     | 
| 
         @@ -219,9 +254,8 @@ module Configurable 
     | 
|
| 
       219 
254 
     | 
    
         
             
                #   array_or_nil.call(nil)    # => nil
         
     | 
| 
       220 
255 
     | 
    
         
             
                def array_or_nil(); ARRAY_OR_NIL; end
         
     | 
| 
       221 
256 
     | 
    
         | 
| 
       222 
     | 
    
         
            -
                # default attributes {:arg_name => "'[a, b, c]'"}
         
     | 
| 
       223 
257 
     | 
    
         
             
                ARRAY_OR_NIL = yaml(Array, nil)
         
     | 
| 
       224 
     | 
    
         
            -
                 
     | 
| 
      
 258 
     | 
    
         
            +
                register_as ARRAY, ARRAY_OR_NIL
         
     | 
| 
       225 
259 
     | 
    
         | 
| 
       226 
260 
     | 
    
         
             
                # Returns a block that checks the input is an array,
         
     | 
| 
       227 
261 
     | 
    
         
             
                # then yamlizes each string value of the array.
         
     | 
| 
         @@ -254,9 +288,9 @@ module Configurable 
     | 
|
| 
       254 
288 
     | 
    
         
             
                #
         
     | 
| 
       255 
289 
     | 
    
         
             
                def hash(); HASH; end
         
     | 
| 
       256 
290 
     | 
    
         | 
| 
       257 
     | 
    
         
            -
                # default attributes {: 
     | 
| 
      
 291 
     | 
    
         
            +
                # default attributes {:type => :hash, :example => "{one: 1, two: 2}"}
         
     | 
| 
       258 
292 
     | 
    
         
             
                HASH = yaml(Hash)
         
     | 
| 
       259 
     | 
    
         
            -
                register HASH, : 
     | 
| 
      
 293 
     | 
    
         
            +
                register HASH, :type => :hash, :example => "{one: 1, two: 2}"
         
     | 
| 
       260 
294 
     | 
    
         | 
| 
       261 
295 
     | 
    
         
             
                # Same as hash but allows nil:
         
     | 
| 
       262 
296 
     | 
    
         
             
                #
         
     | 
| 
         @@ -264,9 +298,8 @@ module Configurable 
     | 
|
| 
       264 
298 
     | 
    
         
             
                #   hash_or_nil.call(nil)          # => nil
         
     | 
| 
       265 
299 
     | 
    
         
             
                def hash_or_nil(); HASH_OR_NIL; end
         
     | 
| 
       266 
300 
     | 
    
         | 
| 
       267 
     | 
    
         
            -
                # default attributes {:arg_name => "'{one: 1, two: 2}'"}
         
     | 
| 
       268 
301 
     | 
    
         
             
                HASH_OR_NIL = yaml(Hash, nil)
         
     | 
| 
       269 
     | 
    
         
            -
                 
     | 
| 
      
 302 
     | 
    
         
            +
                register_as HASH, HASH_OR_NIL
         
     | 
| 
       270 
303 
     | 
    
         | 
| 
       271 
304 
     | 
    
         
             
                # Returns a block that checks the input is an integer.
         
     | 
| 
       272 
305 
     | 
    
         
             
                # String inputs are loaded as yaml first.
         
     | 
| 
         @@ -279,15 +312,20 @@ module Configurable 
     | 
|
| 
       279 
312 
     | 
    
         
             
                #   integer.call('str')       # => ValidationError
         
     | 
| 
       280 
313 
     | 
    
         
             
                #
         
     | 
| 
       281 
314 
     | 
    
         
             
                def integer(); INTEGER; end
         
     | 
| 
      
 315 
     | 
    
         
            +
                
         
     | 
| 
      
 316 
     | 
    
         
            +
                # default attributes {:type => :integer, :example => "2"}
         
     | 
| 
       282 
317 
     | 
    
         
             
                INTEGER = yaml(Integer)
         
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
      
 318 
     | 
    
         
            +
                register INTEGER, :type => :integer, :example => "2"
         
     | 
| 
      
 319 
     | 
    
         
            +
                
         
     | 
| 
       284 
320 
     | 
    
         
             
                # Same as integer but allows nil:
         
     | 
| 
       285 
321 
     | 
    
         
             
                #
         
     | 
| 
       286 
322 
     | 
    
         
             
                #   integer_or_nil.call('~')  # => nil
         
     | 
| 
       287 
323 
     | 
    
         
             
                #   integer_or_nil.call(nil)  # => nil
         
     | 
| 
       288 
324 
     | 
    
         
             
                def integer_or_nil(); INTEGER_OR_NIL; end
         
     | 
| 
      
 325 
     | 
    
         
            +
                
         
     | 
| 
       289 
326 
     | 
    
         
             
                INTEGER_OR_NIL = yaml(Integer, nil)
         
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
      
 327 
     | 
    
         
            +
                register_as INTEGER, INTEGER_OR_NIL
         
     | 
| 
      
 328 
     | 
    
         
            +
                
         
     | 
| 
       291 
329 
     | 
    
         
             
                # Returns a block that checks the input is a float.
         
     | 
| 
       292 
330 
     | 
    
         
             
                # String inputs are loaded as yaml first.
         
     | 
| 
       293 
331 
     | 
    
         
             
                #
         
     | 
| 
         @@ -300,14 +338,19 @@ module Configurable 
     | 
|
| 
       300 
338 
     | 
    
         
             
                #   float.call('str')         # => ValidationError
         
     | 
| 
       301 
339 
     | 
    
         
             
                #
         
     | 
| 
       302 
340 
     | 
    
         
             
                def float(); FLOAT; end
         
     | 
| 
      
 341 
     | 
    
         
            +
                
         
     | 
| 
      
 342 
     | 
    
         
            +
                # default attributes {:type => :float, :example => "2.2, 2.0e+2"}
         
     | 
| 
       303 
343 
     | 
    
         
             
                FLOAT = yaml(Float)
         
     | 
| 
       304 
     | 
    
         
            -
             
     | 
| 
      
 344 
     | 
    
         
            +
                register FLOAT, :type => :float, :example => "2.2, 2.0e+2"
         
     | 
| 
      
 345 
     | 
    
         
            +
                
         
     | 
| 
       305 
346 
     | 
    
         
             
                # Same as float but allows nil:
         
     | 
| 
       306 
347 
     | 
    
         
             
                #
         
     | 
| 
       307 
348 
     | 
    
         
             
                #   float_or_nil.call('~')    # => nil
         
     | 
| 
       308 
349 
     | 
    
         
             
                #   float_or_nil.call(nil)    # => nil
         
     | 
| 
       309 
350 
     | 
    
         
             
                def float_or_nil(); FLOAT_OR_NIL; end
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
       310 
352 
     | 
    
         
             
                FLOAT_OR_NIL = yaml(Float, nil)
         
     | 
| 
      
 353 
     | 
    
         
            +
                register_as FLOAT, FLOAT_OR_NIL
         
     | 
| 
       311 
354 
     | 
    
         | 
| 
       312 
355 
     | 
    
         
             
                # Returns a block that checks the input is a number.
         
     | 
| 
       313 
356 
     | 
    
         
             
                # String inputs are loaded as yaml first.
         
     | 
| 
         @@ -322,14 +365,19 @@ module Configurable 
     | 
|
| 
       322 
365 
     | 
    
         
             
                #   num.call('str')         # => ValidationError
         
     | 
| 
       323 
366 
     | 
    
         
             
                #
         
     | 
| 
       324 
367 
     | 
    
         
             
                def num(); NUMERIC; end
         
     | 
| 
      
 368 
     | 
    
         
            +
                
         
     | 
| 
      
 369 
     | 
    
         
            +
                # default attributes {:type => :num, :example => "2, 2.2, 2.0e+2"}
         
     | 
| 
       325 
370 
     | 
    
         
             
                NUMERIC = yaml(Numeric)
         
     | 
| 
       326 
     | 
    
         
            -
             
     | 
| 
      
 371 
     | 
    
         
            +
                register NUMERIC, :type => :num, :example => "2, 2.2, 2.0e+2"
         
     | 
| 
      
 372 
     | 
    
         
            +
                
         
     | 
| 
       327 
373 
     | 
    
         
             
                # Same as num but allows nil:
         
     | 
| 
       328 
374 
     | 
    
         
             
                #
         
     | 
| 
       329 
375 
     | 
    
         
             
                #   num_or_nil.call('~')    # => nil
         
     | 
| 
       330 
376 
     | 
    
         
             
                #   num_or_nil.call(nil)    # => nil
         
     | 
| 
       331 
377 
     | 
    
         
             
                def num_or_nil(); NUMERIC_OR_NIL; end
         
     | 
| 
      
 378 
     | 
    
         
            +
                
         
     | 
| 
       332 
379 
     | 
    
         
             
                NUMERIC_OR_NIL = yaml(Numeric, nil)
         
     | 
| 
      
 380 
     | 
    
         
            +
                register_as NUMERIC, NUMERIC_OR_NIL
         
     | 
| 
       333 
381 
     | 
    
         | 
| 
       334 
382 
     | 
    
         
             
                # Returns a block that checks the input is a regexp. String inputs are
         
     | 
| 
       335 
383 
     | 
    
         
             
                # loaded as yaml; if the result is not a regexp, it is converted to
         
     | 
| 
         @@ -349,10 +397,7 @@ module Configurable 
     | 
|
| 
       349 
397 
     | 
    
         
             
                def regexp(); REGEXP; end
         
     | 
| 
       350 
398 
     | 
    
         
             
                regexp_block = lambda do |input|
         
     | 
| 
       351 
399 
     | 
    
         
             
                  if input.kind_of?(String)
         
     | 
| 
       352 
     | 
    
         
            -
                     
     | 
| 
       353 
     | 
    
         
            -
                      input = validate(YAML.load(input), [Regexp]) {|obj| input }
         
     | 
| 
       354 
     | 
    
         
            -
                    rescue(ArgumentError)
         
     | 
| 
       355 
     | 
    
         
            -
                    end
         
     | 
| 
      
 400 
     | 
    
         
            +
                    input = load_if_yaml(input, Regexp)
         
     | 
| 
       356 
401 
     | 
    
         
             
                  end
         
     | 
| 
       357 
402 
     | 
    
         | 
| 
       358 
403 
     | 
    
         
             
                  if input.kind_of?(String)
         
     | 
| 
         @@ -361,7 +406,10 @@ module Configurable 
     | 
|
| 
       361 
406 
     | 
    
         | 
| 
       362 
407 
     | 
    
         
             
                  validate(input, [Regexp])
         
     | 
| 
       363 
408 
     | 
    
         
             
                end
         
     | 
| 
      
 409 
     | 
    
         
            +
                
         
     | 
| 
      
 410 
     | 
    
         
            +
                # default attributes {:type => :regexp, :example => "/regexp/i"}
         
     | 
| 
       364 
411 
     | 
    
         
             
                REGEXP = regexp_block
         
     | 
| 
      
 412 
     | 
    
         
            +
                register REGEXP, :type => :regexp, :example => "/regexp/i"
         
     | 
| 
       365 
413 
     | 
    
         | 
| 
       366 
414 
     | 
    
         
             
                # Same as regexp but allows nil. Note the special behavior of the nil
         
     | 
| 
       367 
415 
     | 
    
         
             
                # string '~' -- rather than being converted to a regexp, it is processed
         
     | 
| 
         @@ -376,7 +424,9 @@ module Configurable 
     | 
|
| 
       376 
424 
     | 
    
         
             
                  else REGEXP[input]
         
     | 
| 
       377 
425 
     | 
    
         
             
                  end
         
     | 
| 
       378 
426 
     | 
    
         
             
                end
         
     | 
| 
      
 427 
     | 
    
         
            +
                
         
     | 
| 
       379 
428 
     | 
    
         
             
                REGEXP_OR_NIL = regexp_or_nil_block
         
     | 
| 
      
 429 
     | 
    
         
            +
                register_as REGEXP, REGEXP_OR_NIL
         
     | 
| 
       380 
430 
     | 
    
         | 
| 
       381 
431 
     | 
    
         
             
                # Returns a block that checks the input is a range. String inputs are
         
     | 
| 
       382 
432 
     | 
    
         
             
                # loaded as yaml; if the result is still a string, it is split into a
         
     | 
| 
         @@ -398,10 +448,7 @@ module Configurable 
     | 
|
| 
       398 
448 
     | 
    
         
             
                def range(); RANGE; end
         
     | 
| 
       399 
449 
     | 
    
         
             
                range_block = lambda do |input|
         
     | 
| 
       400 
450 
     | 
    
         
             
                  if input.kind_of?(String)
         
     | 
| 
       401 
     | 
    
         
            -
                     
     | 
| 
       402 
     | 
    
         
            -
                      input = validate(YAML.load(input), [Range]) {|obj| input }
         
     | 
| 
       403 
     | 
    
         
            -
                    rescue(ArgumentError)
         
     | 
| 
       404 
     | 
    
         
            -
                    end
         
     | 
| 
      
 451 
     | 
    
         
            +
                    input = load_if_yaml(input, Range)
         
     | 
| 
       405 
452 
     | 
    
         
             
                  end
         
     | 
| 
       406 
453 
     | 
    
         | 
| 
       407 
454 
     | 
    
         
             
                  if input.kind_of?(String) && input =~ /^([^.]+)(\.{2,3})([^.]+)$/
         
     | 
| 
         @@ -410,8 +457,11 @@ module Configurable 
     | 
|
| 
       410 
457 
     | 
    
         | 
| 
       411 
458 
     | 
    
         
             
                  validate(input, [Range])
         
     | 
| 
       412 
459 
     | 
    
         
             
                end
         
     | 
| 
      
 460 
     | 
    
         
            +
                
         
     | 
| 
      
 461 
     | 
    
         
            +
                # default attributes {:type => :range, :example => "min..max"}
         
     | 
| 
       413 
462 
     | 
    
         
             
                RANGE = range_block
         
     | 
| 
       414 
     | 
    
         
            -
             
     | 
| 
      
 463 
     | 
    
         
            +
                register RANGE, :type => :range, :example => "min..max"
         
     | 
| 
      
 464 
     | 
    
         
            +
                
         
     | 
| 
       415 
465 
     | 
    
         
             
                # Same as range but allows nil:
         
     | 
| 
       416 
466 
     | 
    
         
             
                #
         
     | 
| 
       417 
467 
     | 
    
         
             
                #   range_or_nil.call('~')    # => nil
         
     | 
| 
         @@ -423,7 +473,9 @@ module Configurable 
     | 
|
| 
       423 
473 
     | 
    
         
             
                  else RANGE[input]
         
     | 
| 
       424 
474 
     | 
    
         
             
                  end
         
     | 
| 
       425 
475 
     | 
    
         
             
                end
         
     | 
| 
      
 476 
     | 
    
         
            +
                
         
     | 
| 
       426 
477 
     | 
    
         
             
                RANGE_OR_NIL = range_or_nil_block
         
     | 
| 
      
 478 
     | 
    
         
            +
                register_as RANGE, RANGE_OR_NIL
         
     | 
| 
       427 
479 
     | 
    
         | 
| 
       428 
480 
     | 
    
         
             
                # Returns a block that checks the input is a Time. String inputs are 
         
     | 
| 
       429 
481 
     | 
    
         
             
                # loaded using Time.parse and then converted into times.  Parsed times 
         
     | 
| 
         @@ -460,8 +512,11 @@ module Configurable 
     | 
|
| 
       460 
512 
     | 
    
         
             
                  input = Time.parse(input) if input.kind_of?(String)
         
     | 
| 
       461 
513 
     | 
    
         
             
                  validate(input, [Time])
         
     | 
| 
       462 
514 
     | 
    
         
             
                end
         
     | 
| 
      
 515 
     | 
    
         
            +
                
         
     | 
| 
      
 516 
     | 
    
         
            +
                # default attributes {:type => :time, :example => "2008-08-08 08:00:00"}
         
     | 
| 
       463 
517 
     | 
    
         
             
                TIME = time_block
         
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
      
 518 
     | 
    
         
            +
                register TIME, :type => :time, :example => "2008-08-08 08:00:00"
         
     | 
| 
      
 519 
     | 
    
         
            +
                
         
     | 
| 
       465 
520 
     | 
    
         
             
                # Same as time but allows nil:
         
     | 
| 
       466 
521 
     | 
    
         
             
                #
         
     | 
| 
       467 
522 
     | 
    
         
             
                #   time_or_nil.call('~')    # => nil
         
     | 
| 
         @@ -474,7 +529,119 @@ module Configurable 
     | 
|
| 
       474 
529 
     | 
    
         
             
                  else TIME[input]
         
     | 
| 
       475 
530 
     | 
    
         
             
                  end
         
     | 
| 
       476 
531 
     | 
    
         
             
                end 
         
     | 
| 
      
 532 
     | 
    
         
            +
                
         
     | 
| 
       477 
533 
     | 
    
         
             
                TIME_OR_NIL = time_or_nil_block
         
     | 
| 
      
 534 
     | 
    
         
            +
                register_as TIME, TIME_OR_NIL
         
     | 
| 
      
 535 
     | 
    
         
            +
                
         
     | 
| 
      
 536 
     | 
    
         
            +
                # Returns a block that only allows the specified values.  Select can take
         
     | 
| 
      
 537 
     | 
    
         
            +
                # a block that will validate each individual value.
         
     | 
| 
      
 538 
     | 
    
         
            +
                #
         
     | 
| 
      
 539 
     | 
    
         
            +
                #   s = select(1,2,3, &integer)
         
     | 
| 
      
 540 
     | 
    
         
            +
                #   s.class                      # => Proc
         
     | 
| 
      
 541 
     | 
    
         
            +
                #   s.call(1)                    # => 1
         
     | 
| 
      
 542 
     | 
    
         
            +
                #   s.call('3')                  # => 3
         
     | 
| 
      
 543 
     | 
    
         
            +
                #
         
     | 
| 
      
 544 
     | 
    
         
            +
                #   s.call(nil)                  # => ValidationError
         
     | 
| 
      
 545 
     | 
    
         
            +
                #   s.call(0)                    # => ValidationError
         
     | 
| 
      
 546 
     | 
    
         
            +
                #   s.call('4')                  # => ValidationError
         
     | 
| 
      
 547 
     | 
    
         
            +
                #
         
     | 
| 
      
 548 
     | 
    
         
            +
                # The select block is registered with these default attributes: 
         
     | 
| 
      
 549 
     | 
    
         
            +
                #
         
     | 
| 
      
 550 
     | 
    
         
            +
                #  {:type => :select, :values => values}
         
     | 
| 
      
 551 
     | 
    
         
            +
                #
         
     | 
| 
      
 552 
     | 
    
         
            +
                def select(*values, &validation)
         
     | 
| 
      
 553 
     | 
    
         
            +
                  block = lambda do |input|
         
     | 
| 
      
 554 
     | 
    
         
            +
                    input = validation.call(input) if validation
         
     | 
| 
      
 555 
     | 
    
         
            +
                    validate(input, values)
         
     | 
| 
      
 556 
     | 
    
         
            +
                  end
         
     | 
| 
      
 557 
     | 
    
         
            +
                  
         
     | 
| 
      
 558 
     | 
    
         
            +
                  register(block, :type => :select, :values => values)
         
     | 
| 
      
 559 
     | 
    
         
            +
                end
         
     | 
| 
      
 560 
     | 
    
         
            +
                
         
     | 
| 
      
 561 
     | 
    
         
            +
                # Returns a block that checks the input is an array, and that each member
         
     | 
| 
      
 562 
     | 
    
         
            +
                # of the array is one of the specified values.  A block may be provided
         
     | 
| 
      
 563 
     | 
    
         
            +
                # to validate each individual value.
         
     | 
| 
      
 564 
     | 
    
         
            +
                #
         
     | 
| 
      
 565 
     | 
    
         
            +
                #   s = list_select(1,2,3, &integer)
         
     | 
| 
      
 566 
     | 
    
         
            +
                #   s.class                      # => Proc
         
     | 
| 
      
 567 
     | 
    
         
            +
                #   s.call([1])                  # => [1]
         
     | 
| 
      
 568 
     | 
    
         
            +
                #   s.call([1, '3'])             # => [1, 3]
         
     | 
| 
      
 569 
     | 
    
         
            +
                #   s.call([])                   # => []
         
     | 
| 
      
 570 
     | 
    
         
            +
                #
         
     | 
| 
      
 571 
     | 
    
         
            +
                #   s.call(1)                    # => ValidationError
         
     | 
| 
      
 572 
     | 
    
         
            +
                #   s.call([nil])                # => ValidationError
         
     | 
| 
      
 573 
     | 
    
         
            +
                #   s.call([0])                  # => ValidationError
         
     | 
| 
      
 574 
     | 
    
         
            +
                #   s.call(['4'])                # => ValidationError
         
     | 
| 
      
 575 
     | 
    
         
            +
                #
         
     | 
| 
      
 576 
     | 
    
         
            +
                # The list_select block is registered with these default attributes: 
         
     | 
| 
      
 577 
     | 
    
         
            +
                #
         
     | 
| 
      
 578 
     | 
    
         
            +
                #  {:type => :list_select, :values => values, :split => ','}
         
     | 
| 
      
 579 
     | 
    
         
            +
                #
         
     | 
| 
      
 580 
     | 
    
         
            +
                def list_select(*values, &validation)
         
     | 
| 
      
 581 
     | 
    
         
            +
                  block = lambda do |input|
         
     | 
| 
      
 582 
     | 
    
         
            +
                    args = validate(input, [Array])
         
     | 
| 
      
 583 
     | 
    
         
            +
                    args.collect! {|arg| validation.call(arg) } if validation
         
     | 
| 
      
 584 
     | 
    
         
            +
                    args.each {|arg| validate(arg, values) }
         
     | 
| 
      
 585 
     | 
    
         
            +
                  end
         
     | 
| 
      
 586 
     | 
    
         
            +
                  
         
     | 
| 
      
 587 
     | 
    
         
            +
                  register(block, :type => :list_select, :values => values, :split => ',')
         
     | 
| 
      
 588 
     | 
    
         
            +
                end
         
     | 
| 
      
 589 
     | 
    
         
            +
                
         
     | 
| 
      
 590 
     | 
    
         
            +
                # Returns a block validating the input is an IO or a string.  String inputs
         
     | 
| 
      
 591 
     | 
    
         
            +
                # are expected to be filepaths, but io does not open a file immediately.
         
     | 
| 
      
 592 
     | 
    
         
            +
                #
         
     | 
| 
      
 593 
     | 
    
         
            +
                #   io.class                     # => Proc
         
     | 
| 
      
 594 
     | 
    
         
            +
                #   io.call($stdout)             # => $stdout
         
     | 
| 
      
 595 
     | 
    
         
            +
                #   io.call('/path/to/file')     # => '/path/to/file'
         
     | 
| 
      
 596 
     | 
    
         
            +
                #
         
     | 
| 
      
 597 
     | 
    
         
            +
                #   io.call(nil)                 # => ValidationError
         
     | 
| 
      
 598 
     | 
    
         
            +
                #   io.call(10)                  # => ValidationError
         
     | 
| 
      
 599 
     | 
    
         
            +
                #
         
     | 
| 
      
 600 
     | 
    
         
            +
                # An IO api can be specified to allow other objects to be validated.  This
         
     | 
| 
      
 601 
     | 
    
         
            +
                # is useful for duck-typing an IO when a known subset of methods are needed.
         
     | 
| 
      
 602 
     | 
    
         
            +
                #
         
     | 
| 
      
 603 
     | 
    
         
            +
                #   array_io = io(:<<)
         
     | 
| 
      
 604 
     | 
    
         
            +
                #   array_io.call($stdout)       # => $stdout
         
     | 
| 
      
 605 
     | 
    
         
            +
                #   array_io.call([])            # => []
         
     | 
| 
      
 606 
     | 
    
         
            +
                #   array_io.call(nil)           # => ValidationError
         
     | 
| 
      
 607 
     | 
    
         
            +
                #
         
     | 
| 
      
 608 
     | 
    
         
            +
                def io(*api)
         
     | 
| 
      
 609 
     | 
    
         
            +
                  if api.empty?
         
     | 
| 
      
 610 
     | 
    
         
            +
                    IO_OR_STRING
         
     | 
| 
      
 611 
     | 
    
         
            +
                  else
         
     | 
| 
      
 612 
     | 
    
         
            +
                    block = lambda do |input|
         
     | 
| 
      
 613 
     | 
    
         
            +
                      validate(input, [IO, String]) do
         
     | 
| 
      
 614 
     | 
    
         
            +
                        api.all? {|m| input.respond_to?(m) }
         
     | 
| 
      
 615 
     | 
    
         
            +
                      end
         
     | 
| 
      
 616 
     | 
    
         
            +
                    end
         
     | 
| 
      
 617 
     | 
    
         
            +
                    
         
     | 
| 
      
 618 
     | 
    
         
            +
                    register_as IO_OR_STRING, block
         
     | 
| 
      
 619 
     | 
    
         
            +
                  end
         
     | 
| 
      
 620 
     | 
    
         
            +
                end
         
     | 
| 
      
 621 
     | 
    
         
            +
                
         
     | 
| 
      
 622 
     | 
    
         
            +
                # default attributes {:type => :io, :example => "/path/to/file"}
         
     | 
| 
      
 623 
     | 
    
         
            +
                IO_OR_STRING = check(IO, String)
         
     | 
| 
      
 624 
     | 
    
         
            +
                register IO_OR_STRING, :type => :io, :example => "/path/to/file"
         
     | 
| 
      
 625 
     | 
    
         
            +
                
         
     | 
| 
      
 626 
     | 
    
         
            +
                # Same as io but allows nil:
         
     | 
| 
      
 627 
     | 
    
         
            +
                #
         
     | 
| 
      
 628 
     | 
    
         
            +
                #   io_or_nil.call(nil)          # => nil
         
     | 
| 
      
 629 
     | 
    
         
            +
                #
         
     | 
| 
      
 630 
     | 
    
         
            +
                def io_or_nil(*api)
         
     | 
| 
      
 631 
     | 
    
         
            +
                  if api.empty?
         
     | 
| 
      
 632 
     | 
    
         
            +
                    IO_STRING_OR_NIL
         
     | 
| 
      
 633 
     | 
    
         
            +
                  else
         
     | 
| 
      
 634 
     | 
    
         
            +
                    block = lambda do |input|
         
     | 
| 
      
 635 
     | 
    
         
            +
                      validate(input, [IO, String, nil]) do
         
     | 
| 
      
 636 
     | 
    
         
            +
                        api.all? {|m| input.respond_to?(m) }
         
     | 
| 
      
 637 
     | 
    
         
            +
                      end
         
     | 
| 
      
 638 
     | 
    
         
            +
                    end
         
     | 
| 
      
 639 
     | 
    
         
            +
                    
         
     | 
| 
      
 640 
     | 
    
         
            +
                    register_as IO_STRING_OR_NIL, block
         
     | 
| 
      
 641 
     | 
    
         
            +
                  end  
         
     | 
| 
      
 642 
     | 
    
         
            +
                end
         
     | 
| 
       478 
643 
     | 
    
         | 
| 
      
 644 
     | 
    
         
            +
                IO_STRING_OR_NIL = check(IO, String, nil)
         
     | 
| 
      
 645 
     | 
    
         
            +
                register_as IO_OR_STRING, IO_STRING_OR_NIL
         
     | 
| 
       479 
646 
     | 
    
         
             
              end
         
     | 
| 
       480 
647 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: configurable
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.4. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.4.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors: 
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Simon Chiang
         
     | 
| 
         @@ -9,7 +9,7 @@ autorequire: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
            date: 2009-03- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2009-03-30 00:00:00 -06:00
         
     | 
| 
       13 
13 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       14 
14 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       15 
15 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     |