Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/thor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,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 yo 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 = {})
scope = if options[:for]
Expand Down
33 changes: 22 additions & 11 deletions lib/thor/parser/option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ def initialize(name, options = {})
@group = options[:group].to_s.capitalize if options[:group]
@aliases = Array(options[:aliases])
@hide = options[:hide]
@inverse = options[:inverse]
end

# This parse quick options given as method_options. It makes several
Expand Down Expand Up @@ -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.start_with?("no-")
end
sample = [ sample_banner, inverse_sample ].compact.join(", ")

if aliases.empty?
(" " * padding) << sample
Expand All @@ -110,6 +101,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|no-.*)$/

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!
Expand Down
16 changes: 16 additions & 0 deletions spec/parser/option_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,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")
Expand Down