diff options
author | Lee Jarvis <lee@jrvs.uk> | 2023-02-15 11:28:21 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-15 11:28:21 -0800 |
commit | 2410f313984be1dfe73884251e879b008771535d (patch) | |
tree | 8f36d5b4c65685653e0c8ef3c344d5fe75564fd6 /lib/slop | |
parent | fc4622fc08d7982847ff583ad691ee4ba47f63f8 (diff) | |
parent | becc0305239c2885affb1f57419afac3e5418a88 (diff) | |
download | slop-2410f313984be1dfe73884251e879b008771535d.tar.gz |
Merge pull request #278 from heyvito/feat/validate-types
Add support to optional type validation
Diffstat (limited to 'lib/slop')
-rw-r--r-- | lib/slop/error.rb | 12 | ||||
-rw-r--r-- | lib/slop/option.rb | 20 | ||||
-rwxr-xr-x | lib/slop/options.rb | 4 | ||||
-rw-r--r-- | lib/slop/types.rb | 21 |
4 files changed, 54 insertions, 3 deletions
diff --git a/lib/slop/error.rb b/lib/slop/error.rb index ddfa1a7..b83cab3 100644 --- a/lib/slop/error.rb +++ b/lib/slop/error.rb @@ -38,4 +38,16 @@ module Slop # Suppress with the `suppress_errors` config option. class MissingRequiredOption < Error end + + # Raised when a given option is provided by the user and does not + # match the expected format for that type. This is only raised if + # validate_types is set to true. + class InvalidOptionValue < Error + attr_reader :flag + + def initialize(msg, flag) + super(msg) + @flag = flag + end + end end diff --git a/lib/slop/option.rb b/lib/slop/option.rb index 093b37f..655b283 100644 --- a/lib/slop/option.rb +++ b/lib/slop/option.rb @@ -56,7 +56,11 @@ module Slop raise Slop::MissingArgument.new("missing argument for #{flag}", flags) end else - @value = call(value) + if validate_type? && !valid?(value) && !suppress_errors? + raise Slop::InvalidOptionValue.new("invalid value for #{flag}", flags) + end + + @value = valid?(value) && call(value) end block.call(@value) if block.respond_to?(:call) @@ -107,6 +111,13 @@ module Slop config[:required] end + # Returns true if an exception should be raised when this option value can't + # be parsed into the desired type or does not conform to the expected type's + # format + def validate_type? + config[:validate_type] || config[:validate_types] + end + # Returns all flags joined by a comma. Used by the help string. def flag flags.join(", ") @@ -119,6 +130,13 @@ module Slop key.to_sym end + # Override this if you want to provide a custom validator for a type. This + # method must return whether the provided value is valid for the current + # argument's type + def valid?(value) + true + end + # Returns true if this option should be displayed with dashes transformed into underscores. def underscore_flags? config[:underscore_flags] diff --git a/lib/slop/options.rb b/lib/slop/options.rb index 17e9501..5e71eac 100755 --- a/lib/slop/options.rb +++ b/lib/slop/options.rb @@ -7,6 +7,7 @@ module Slop type: "null", banner: true, underscore_flags: true, + validate_types: false, } # The Array of Option instances we've created. @@ -24,6 +25,9 @@ module Slop # The String banner prefixed to the help string. attr_accessor :banner + # Whether we should validate types of values provided by the user + attr_accessor :validate_types + def initialize(**config, &block) @options = [] @separators = [] diff --git a/lib/slop/types.rb b/lib/slop/types.rb index 83e4a0b..a08537d 100644 --- a/lib/slop/types.rb +++ b/lib/slop/types.rb @@ -22,6 +22,13 @@ module Slop attr_accessor :explicit_value FALSE_VALUES = [false, 'false', 'no', 'off', '0'].freeze + TRUE_VALUES = [true, 'true', 'yes', 'on', '1'].freeze + VALID_VALUES = (FALSE_VALUES + TRUE_VALUES).freeze + + def valid?(value) + return true if value.is_a?(String) && value.start_with?("--") + value.nil? || VALID_VALUES.include?(value) + end def call(value) self.explicit_value = value @@ -52,8 +59,14 @@ module Slop # Cast the option argument to an Integer. class IntegerOption < Option + INT_STRING_REGEXP = /\A[+-]?\d+\z/.freeze + + def valid?(value) + value =~ INT_STRING_REGEXP + end + def call(value) - value =~ /\A[+-]?\d+\z/ && value.to_i + value.to_i end end IntOption = IntegerOption @@ -62,8 +75,12 @@ module Slop class FloatOption < Option FLOAT_STRING_REGEXP = /\A[+-]?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+-]?\d+)?\z/.freeze + def valid?(value) + value =~ FLOAT_STRING_REGEXP + end + def call(value) - value =~ FLOAT_STRING_REGEXP && value.to_f + value.to_f end end |