Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to ignore class options for command #582

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
15 changes: 13 additions & 2 deletions lib/thor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,16 @@ def method_options(options = nil)

alias_method :options, :method_options


# Declares the class options which can be ignored for given command
#
# ==== Parameters
# list<Array>:: List of class options to be ignored
#
def ignore_class_options(list = nil)
@class_options_to_ignore ||= list
end

# Adds an option to the set of method options. If :for is given as option,
# it allows you to change the options from a previous defined command.
#
Expand Down Expand Up @@ -172,7 +182,8 @@ def command_help(shell, command_name)
shell.say "Usage:"
shell.say " #{banner(command)}"
shell.say
class_options_help(shell, nil => command.options.values)
class_options_help(shell, command.ignored_options, nil => command.options.values)

if command.long_description
shell.say "Description:"
shell.print_wrapped(command.long_description, :indent => 2)
Expand Down Expand Up @@ -412,7 +423,7 @@ def create_command(meth) #:nodoc:

if @usage && @desc
base_class = @hide ? Thor::HiddenCommand : Thor::Command
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options, ignore_class_options)
@usage, @desc, @long_desc, @method_options, @hide = nil
true
elsif all_commands[meth] || meth == "method_missing"
Expand Down
13 changes: 9 additions & 4 deletions lib/thor/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ module Base
# config<Hash>:: Configuration for this Thor class.
#
def initialize(args = [], local_options = {}, config = {})
parse_options = self.class.class_options
parse_options = self.class.class_options.dup

ignored_options = config[:current_command] ? config[:current_command].ignored_options : []

parse_options.reject! { |k, _v| ignored_options.include?(k) }

# The start method splits inbound arguments at the first argument
# that looks like an option (starts with - or --). It then calls
Expand Down Expand Up @@ -512,15 +516,16 @@ def handle_argument_error(command, error, args, arity) #:nodoc:
# Prints the class options per group. If an option does not belong to
# any group, it's printed as Class option.
#
def class_options_help(shell, groups = {}) #:nodoc:
def class_options_help(shell, ignored_options = [], groups = {}) #:nodoc:
# Group options by group
class_options.each do |_, value|
class_options.each do |key, value|
groups[value.group] ||= []
groups[value.group] << value
groups[value.group] << value unless ignored_options.include? key
end

# Deal with default group
global_options = groups.delete(nil) || []

print_options(shell, global_options)

# Print all others
Expand Down
6 changes: 3 additions & 3 deletions lib/thor/command.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
class Thor
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :ancestor_name)
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :ignored_options, :ancestor_name)
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/

def initialize(name, description, long_description, usage, options = nil)
super(name.to_s, description, long_description, usage, options || {})
def initialize(name, description, long_description, usage, options = nil, ignored_options = nil)
super(name.to_s, description, long_description, usage, options || {}, ignored_options || [])
end

def initialize_copy(other) #:nodoc:
Expand Down
2 changes: 1 addition & 1 deletion lib/thor/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def class_options_help(shell, groups = {}) #:nodoc:
get_options_from_invocations(groups, class_options) do |klass|
klass.send(:get_options_from_invocations, groups, class_options)
end
super(shell, groups)
super(shell, [], groups)
end

# Get invocations array and merge options from invocations. Those
Expand Down
26 changes: 26 additions & 0 deletions spec/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,32 @@ def hello
content = capture(:stdout) { Enum.help(Thor::Base.shell.new) }
expect(content).to match(/Possible values\: apple, banana/)
end

it "does not display class options in help if it has been ignored for a command" do
help = capture(:stdout) { IgnoreClassOptions.start(%w(help shake)) }

expect(help).not_to match (/-c, --cheese=CHEESE/)
end

it "displays class options in help if it has been not ignored for a command" do
help = capture(:stdout) { IgnoreClassOptions.start(%w(help snack)) }

expect(help).to match (/-c, --cheese=CHEESE/)
end
end

describe "#ignore_class_options" do
it "ignores class options when used ignore_class_options" do
options = IgnoreClassOptions.start(%w(shake --fruit apple --milk 1))

expect(options).to eq ({"fruit"=>"apple", "milk"=>1})
end

it "does not ignore class options when ignore_class_options is not used" do
options_when_not_ignored = IgnoreClassOptions.start(%w(snack --fruit apple --cheese provlone))

expect(options_when_not_ignored).to eq ({ "cheese" => "provlone", "fruit" => "apple" })
end
end

describe "#namespace" do
Expand Down
17 changes: 17 additions & 0 deletions spec/fixtures/ignore_class_options.thor
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class IgnoreClassOptions < Thor
class_option :fruit, :aliases => "-f", :type => :string, :enum => %w(apple banana), :required => true
class_option :cheese, :aliases => "-c", :type => :string, :enum => %w(pepperjack provlone), :required => true

desc "snack", "test"
method_option :vegetable, :aliases => "-v", :type => :string
def snack
options
end

desc "shake", "test"
method_option :milk, :aliases => "-k", :type => :numeric
ignore_class_options [:cheese]
def shake
options
end
end
1 change: 1 addition & 0 deletions spec/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
load File.join(File.dirname(__FILE__), "fixtures", "subcommand.thor")
load File.join(File.dirname(__FILE__), "fixtures", "command.thor")
load File.join(File.dirname(__FILE__), "fixtures", "ignore_class_options.thor")

RSpec.configure do |config|
config.before do
Expand Down