diff options
Diffstat (limited to 'lib/bundler/vendor/thor/lib/thor/parser')
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/parser/argument.rb | 21 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/parser/arguments.rb | 50 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/parser/option.rb | 35 | ||||
-rw-r--r-- | lib/bundler/vendor/thor/lib/thor/parser/options.rb | 50 |
4 files changed, 124 insertions, 32 deletions
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb index dfe7398583..b9e94e4669 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb @@ -24,6 +24,17 @@ class Bundler::Thor validate! # Trigger specific validations end + def print_default + if @type == :array and @default.is_a?(Array) + @default.map { |x| + p = x.gsub('"','\\"') + "\"#{p}\"" + }.join(" ") + else + @default + end + end + def usage required? ? banner : "[#{banner}]" end @@ -41,11 +52,19 @@ class Bundler::Thor end end + def enum_to_s + if enum.respond_to? :join + enum.join(", ") + else + "#{enum.first}..#{enum.last}" + end + end + protected def validate! raise ArgumentError, "An argument cannot be required and have default value." if required? && !default.nil? - raise ArgumentError, "An argument cannot have an enum other than an array." if @enum && !@enum.is_a?(Array) + raise ArgumentError, "An argument cannot have an enum other than an enumerable." if @enum && !@enum.is_a?(Enumerable) end def valid_type?(type) diff --git a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb index 3a5d82cf29..b6f9c9a37a 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb @@ -1,5 +1,5 @@ class Bundler::Thor - class Arguments #:nodoc: # rubocop:disable ClassLength + class Arguments #:nodoc: NUMERIC = /[-+]?(\d*\.\d+|\d+)/ # Receives an array of args and returns two arrays, one with arguments @@ -30,11 +30,7 @@ class Bundler::Thor arguments.each do |argument| if !argument.default.nil? - begin - @assigns[argument.human_name] = argument.default.dup - rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4 - @assigns[argument.human_name] = argument.default - end + @assigns[argument.human_name] = argument.default.dup elsif argument.required? @non_assigned_required << argument end @@ -121,8 +117,18 @@ class Bundler::Thor # def parse_array(name) return shift if peek.is_a?(Array) + array = [] - array << shift while current_is_value? + + while current_is_value? + value = shift + + if !value.empty? + validate_enum_value!(name, value, "Expected all values of '%s' to be one of %s; got %s") + end + + array << value + end array end @@ -138,11 +144,9 @@ class Bundler::Thor end value = $&.index(".") ? shift.to_f : shift.to_i - if @switches.is_a?(Hash) && switch = @switches[name] - if switch.enum && !switch.enum.include?(value) - raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" - end - end + + validate_enum_value!(name, value, "Expected '%s' to be one of %s; got %s") + value end @@ -156,15 +160,27 @@ class Bundler::Thor nil else value = shift - if @switches.is_a?(Hash) && switch = @switches[name] - if switch.enum && !switch.enum.include?(value) - raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}" - end - end + + validate_enum_value!(name, value, "Expected '%s' to be one of %s; got %s") + value end end + # Raises an error if the switch is an enum and the values aren't included on it. + # + def validate_enum_value!(name, value, message) + return unless @switches.is_a?(Hash) + + switch = @switches[name] + + return unless switch + + if switch.enum && !switch.enum.include?(value) + raise MalformattedArgumentError, message % [name, switch.enum_to_s, value] + end + end + # Raises an error if @non_assigned_required array is not empty. # def check_requirement! diff --git a/lib/bundler/vendor/thor/lib/thor/parser/option.rb b/lib/bundler/vendor/thor/lib/thor/parser/option.rb index 5a5af6f888..c6af4e1e87 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/option.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/option.rb @@ -11,7 +11,7 @@ class Bundler::Thor super @lazy_default = options[:lazy_default] @group = options[:group].to_s.capitalize if options[:group] - @aliases = Array(options[:aliases]) + @aliases = normalize_aliases(options[:aliases]) @hide = options[:hide] end @@ -58,7 +58,7 @@ class Bundler::Thor default = nil if VALID_TYPES.include?(value) value - elsif required = (value == :required) # rubocop:disable AssignmentInCondition + elsif required = (value == :required) # rubocop:disable Lint/AssignmentInCondition :string end when TrueClass, FalseClass @@ -69,7 +69,7 @@ class Bundler::Thor value.class.name.downcase.to_sym end - new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases) + new(name.to_s, required: required, type: type, default: default, aliases: aliases) end def switch_name @@ -90,13 +90,26 @@ class Bundler::Thor sample = "[#{sample}]".dup unless required? if boolean? - sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.start_with?("no-") + sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.match(/\Ano[\-_]/) end + aliases_for_usage.ljust(padding) + sample + end + + def aliases_for_usage if aliases.empty? - (" " * padding) << sample + "" + else + "#{aliases.join(', ')}, " + end + end + + def show_default? + case default + when TrueClass, FalseClass + true else - "#{aliases.join(', ')}, #{sample}" + super end end @@ -138,8 +151,8 @@ class Bundler::Thor raise ArgumentError, err elsif @check_default_type == nil Bundler::Thor.deprecation_warning "#{err}.\n" + - 'This will be rejected in the future unless you explicitly pass the options `check_default_type: false`' + - ' or call `allow_incompatible_default_type!` in your code' + "This will be rejected in the future unless you explicitly pass the options `check_default_type: false`" + + " or call `allow_incompatible_default_type!` in your code" end end end @@ -155,5 +168,11 @@ class Bundler::Thor def dasherize(str) (str.length > 1 ? "--" : "-") + str.tr("_", "-") end + + private + + def normalize_aliases(aliases) + Array(aliases).map { |short| short.to_s.sub(/^(?!\-)/, "-") } + end end end diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb index 5bd97aba6f..978e76b132 100644 --- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb +++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb @@ -1,5 +1,5 @@ class Bundler::Thor - class Options < Arguments #:nodoc: # rubocop:disable ClassLength + class Options < Arguments #:nodoc: LONG_RE = /^(--\w+(?:-\w+)*)$/ SHORT_RE = /^(-[a-z])$/i EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i @@ -29,8 +29,10 @@ class Bundler::Thor # # If +stop_on_unknown+ is true, #parse will stop as soon as it encounters # an unknown option or a regular argument. - def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false) + def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false, relations = {}) @stop_on_unknown = stop_on_unknown + @exclusives = (relations[:exclusive_option_names] || []).select{|array| !array.empty?} + @at_least_ones = (relations[:at_least_one_option_names] || []).select{|array| !array.empty?} @disable_required_check = disable_required_check options = hash_options.values super(options) @@ -50,8 +52,7 @@ class Bundler::Thor options.each do |option| @switches[option.switch_name] = option - option.aliases.each do |short| - name = short.to_s.sub(/^(?!\-)/, "-") + option.aliases.each do |name| @shorts[name] ||= option.switch_name end end @@ -85,7 +86,7 @@ class Bundler::Thor super(arg) end - def parse(args) # rubocop:disable MethodLength + def parse(args) # rubocop:disable Metrics/MethodLength @pile = args.dup @is_treated_as_value = false @parsing_options = true @@ -132,12 +133,38 @@ class Bundler::Thor end check_requirement! unless @disable_required_check + check_exclusive! + check_at_least_one! assigns = Bundler::Thor::CoreExt::HashWithIndifferentAccess.new(@assigns) assigns.freeze assigns end + def check_exclusive! + opts = @assigns.keys + # When option A and B are exclusive, if A and B are given at the same time, + # the diffrence of argument array size will decrease. + found = @exclusives.find{ |ex| (ex - opts).size < ex.size - 1 } + if found + names = names_to_switch_names(found & opts).map{|n| "'#{n}'"} + class_name = self.class.name.split("::").last.downcase + fail ExclusiveArgumentError, "Found exclusive #{class_name} #{names.join(", ")}" + end + end + + def check_at_least_one! + opts = @assigns.keys + # When at least one is required of the options A and B, + # if the both options were not given, none? would be true. + found = @at_least_ones.find{ |one_reqs| one_reqs.none?{ |o| opts.include? o} } + if found + names = names_to_switch_names(found).map{|n| "'#{n}'"} + class_name = self.class.name.split("::").last.downcase + fail AtLeastOneRequiredArgumentError, "Not found at least one of required #{class_name} #{names.join(", ")}" + end + end + def check_unknown! to_check = @stopped_parsing_after_extra_index ? @extra[0...@stopped_parsing_after_extra_index] : @extra @@ -148,6 +175,17 @@ class Bundler::Thor protected + # Option names changes to swith name or human name + def names_to_switch_names(names = []) + @switches.map do |_, o| + if names.include? o.name + o.respond_to?(:switch_name) ? o.switch_name : o.human_name + else + nil + end + end.compact + end + def assign_result!(option, result) if option.repeatable && option.type == :hash (@assigns[option.human_name] ||= {}).merge!(result) @@ -194,7 +232,7 @@ class Bundler::Thor end def switch_option(arg) - if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition + if match = no_or_skip?(arg) # rubocop:disable Lint/AssignmentInCondition @switches[arg] || @switches["--#{match}"] else @switches[arg] |