diff --git a/lib/thor.rb b/lib/thor.rb index cf999e6e..13225ca0 100644 --- a/lib/thor.rb +++ b/lib/thor.rb @@ -159,6 +159,8 @@ def method_options(options = nil) # :type - The type of the argument, can be :string, :hash, :array, :numeric or :boolean. # :banner - String to show on usage notes. # :hide - If you want to hide this option from the help. + # :inverse - false if you don't want an inverse option of your boolean type, String or Symbol + # if you want to override the inverse option name. # def method_option(name, options = {}) unless [ Symbol, String ].any? { |klass| name.is_a?(klass) } diff --git a/lib/thor/parser/option.rb b/lib/thor/parser/option.rb index b1a99431..c909c5cf 100644 --- a/lib/thor/parser/option.rb +++ b/lib/thor/parser/option.rb @@ -13,6 +13,7 @@ def initialize(name, options = {}) @group = options[:group].to_s.capitalize if options[:group] @aliases = normalize_aliases(options[:aliases]) @hide = options[:hide] + @inverse = options[:inverse] end # This parse quick options given as method_options. It makes several @@ -81,17 +82,7 @@ def human_name end def usage(padding = 0) - sample = if banner && !banner.to_s.empty? - "#{switch_name}=#{banner}".dup - else - switch_name - end - - sample = "[#{sample}]".dup unless required? - - if boolean? - sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.match(/\Ano[\-_]/) - end + sample = [ sample_banner, inverse_sample ].compact.join(", ") aliases_for_usage.ljust(padding) + sample end @@ -123,6 +114,26 @@ def #{type}? protected + def sample_banner + sample_banner = if banner && !banner.to_s.empty? + "#{switch_name}=#{banner}".dup + else + switch_name + end + required? ? sample_banner : "[#{sample_banner}]" + end + + def inverse_sample + return if !boolean? || name =~ /^(force|\Ano[\-_])$/ + + case @inverse + when Symbol, String + "[#{dasherize(@inverse.to_s)}]" + when nil, true + "[#{dasherize('no-' + human_name)}]" + end + end + def validate! raise ArgumentError, "An option cannot be boolean and required." if boolean? && required? validate_default_type! diff --git a/spec/parser/option_spec.rb b/spec/parser/option_spec.rb index 54aba1bb..8bd0f72e 100644 --- a/spec/parser/option_spec.rb +++ b/spec/parser/option_spec.rb @@ -249,6 +249,22 @@ def option(name, options = {}) expect(option(:foo, required: false, type: :string, banner: "").usage).to eq("[--foo]") end + it "suppresses the creation of a --no-option when explicitly requested" do + expect(option("bar", type: :boolean, :inverse => false).usage).to_not include("[--no-bar]") + end + + it "allow to override the inverse option" do + expect(option("colorful", type: :boolean, :inverse => :monochromatic).usage).to include("[--monochromatic]") + end + + it "creates the inversion flag by default" do + expect(option("bar", type: :boolean).usage).to include("[--no-bar]") + end + + it "creates the inversion flag when requested" do + expect(option("bar", type: :boolean, :inverse => true).usage).to include("[--no-bar]") + end + describe "with required values" do it "does not show the usage between brackets" do expect(parse(:foo, :required).usage).to eq("--foo=FOO")