Skip to content

Commit

Permalink
Merge pull request #545 from erikhuda/fix-disable_class_options
Browse files Browse the repository at this point in the history
Add disable_required_check! and make disable the check in help
  • Loading branch information
rafaelfranca committed Feb 28, 2017
2 parents e675416 + 35ab20d commit 2b82ae3
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,4 +1,7 @@
## 0.20.0
* Add `disable_required_check!` to disable check for required options in some commands.
It is a substitute of `disable_class_options` that was not working as intended.

* Add `inject_into_module`.

## 0.19.4, release 2016-11-28
Expand Down
29 changes: 21 additions & 8 deletions lib/thor.rb
Expand Up @@ -158,10 +158,6 @@ def method_option(name, options = {})
end
alias_method :option, :method_option

def disable_class_options
@disable_class_options = true
end

# Prints help information for the given command.
#
# ==== Parameters
Expand Down Expand Up @@ -329,12 +325,31 @@ def stop_on_unknown_option?(command) #:nodoc:
command && stop_on_unknown_option.include?(command.name.to_sym)
end

# Disable the check for required options for the given commands.
# This is useful if you have a command that does not need the required options
# to work, like help.
#
# ==== Parameters
# Symbol ...:: A list of commands that should be affected.
def disable_required_check!(*command_names)
disable_required_check.merge(command_names)
end

def disable_required_check?(command) #:nodoc:
command && disable_required_check.include?(command.name.to_sym)
end

protected

def stop_on_unknown_option #:nodoc:
@stop_on_unknown_option ||= Set.new
end

# help command has the required check disabled by default.
def disable_required_check #:nodoc:
@disable_required_check ||= Set.new([:help])
end

# The method responsible for dispatching given the args.
def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength
meth ||= retrieve_command_name(given_args)
Expand Down Expand Up @@ -393,12 +408,11 @@ def create_command(meth) #:nodoc:
@usage ||= nil
@desc ||= nil
@long_desc ||= nil
@disable_class_options ||= nil

if @usage && @desc
base_class = @hide ? Thor::HiddenCommand : Thor::Command
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options, @disable_class_options)
@usage, @desc, @long_desc, @method_options, @hide, @disable_class_options = nil
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
@usage, @desc, @long_desc, @method_options, @hide = nil
true
elsif all_commands[meth] || meth == "method_missing"
true
Expand Down Expand Up @@ -480,7 +494,6 @@ def help(command = nil, subcommand = true); super; end
map HELP_MAPPINGS => :help

desc "help [COMMAND]", "Describe available commands or one specific command"
disable_class_options
def help(command = nil, subcommand = false)
if command
if self.class.subcommands.include? command
Expand Down
11 changes: 9 additions & 2 deletions lib/thor/base.rb
Expand Up @@ -42,7 +42,7 @@ module Base
# config<Hash>:: Configuration for this Thor class.
#
def initialize(args = [], local_options = {}, config = {})
parse_options = config[:current_command] && config[:current_command].disable_class_options ? {} : self.class.class_options
parse_options = self.class.class_options

# The start method splits inbound arguments at the first argument
# that looks like an option (starts with - or --). It then calls
Expand All @@ -65,7 +65,8 @@ def initialize(args = [], local_options = {}, config = {})
# declared options from the array. This will leave us with
# a list of arguments that weren't declared.
stop_on_unknown = self.class.stop_on_unknown_option? config[:current_command]
opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown)
disable_required_check = self.class.disable_required_check? config[:current_command]
opts = Thor::Options.new(parse_options, hash_options, stop_on_unknown, disable_required_check)
self.options = opts.parse(array_options)
self.options = config[:class_options].merge(options) if config[:class_options]

Expand Down Expand Up @@ -157,6 +158,12 @@ def stop_on_unknown_option?(command_name) #:nodoc:
false
end

# If true, option set will not suspend the execution of the command when
# a required option is not provided.
def disable_required_check?(command_name) #:nodoc:
false
end

# If you want only strict string args (useful when cascading thor classes),
# call strict_args_position! This is disabled by default to allow dynamic
# invocations.
Expand Down
6 changes: 3 additions & 3 deletions lib/thor/command.rb
@@ -1,9 +1,9 @@
class Thor
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :disable_class_options, :ancestor_name)
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :ancestor_name)
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/

def initialize(name, description, long_description, usage, options = nil, disable_class_options = false)
super(name.to_s, description, long_description, usage, options || {}, disable_class_options)
def initialize(name, description, long_description, usage, options = nil)
super(name.to_s, description, long_description, usage, options || {})
end

def initialize_copy(other) #:nodoc:
Expand Down
5 changes: 3 additions & 2 deletions lib/thor/parser/options.rb
Expand Up @@ -29,8 +29,9 @@ def self.to_switches(options)
#
# 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)
def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false)
@stop_on_unknown = stop_on_unknown
@disable_required_check = disable_required_check
options = hash_options.values
super(options)

Expand Down Expand Up @@ -111,7 +112,7 @@ def parse(args) # rubocop:disable MethodLength
end
end

check_requirement!
check_requirement! unless @disable_required_check

assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
assigns.freeze
Expand Down
58 changes: 58 additions & 0 deletions spec/thor_spec.rb
Expand Up @@ -159,6 +159,64 @@ def boring(*args)
end
end

describe "#disable_required_check!" do
my_script = Class.new(Thor) do
class_option "foo", :required => true

disable_required_check! :boring

desc "exec", "Run a command"
def exec(*args)
[options, args]
end

desc "boring", "An ordinary command"
def boring(*args)
[options, args]
end
end

it "does not check the required option in the given command" do
expect(my_script.start(%w(boring command))).to eq [{}, %w(command)]
end

it "does check the required option of the remaining command" do
content = capture(:stderr) { my_script.start(%w(exec command)) }
expect(content).to eq "No value provided for required options '--foo'\n"
end

it "does affects help by default" do
expect(my_script.disable_required_check?(double(:name => "help"))).to be true
end

context "when provided with multiple command names" do
klass = Class.new(Thor) do
disable_required_check! :foo, :bar
end

it "affects all specified commands" do
expect(klass.disable_required_check?(double(:name => "help"))).to be true
expect(klass.disable_required_check?(double(:name => "foo"))).to be true
expect(klass.disable_required_check?(double(:name => "bar"))).to be true
expect(klass.disable_required_check?(double(:name => "baz"))).to be false
end
end

context "when invoked several times" do
klass = Class.new(Thor) do
disable_required_check! :foo
disable_required_check! :bar
end

it "affects all specified commands" do
expect(klass.disable_required_check?(double(:name => "help"))).to be true
expect(klass.disable_required_check?(double(:name => "foo"))).to be true
expect(klass.disable_required_check?(double(:name => "bar"))).to be true
expect(klass.disable_required_check?(double(:name => "baz"))).to be false
end
end
end

describe "#map" do
it "calls the alias of a method if one is provided" do
expect(MyScript.start(%w(-T fish))).to eq(%w(fish))
Expand Down

0 comments on commit 2b82ae3

Please sign in to comment.