Skip to content

Commit 2b82ae3

Browse files
authored
Merge pull request #545 from erikhuda/fix-disable_class_options
Add disable_required_check! and make disable the check in help
2 parents e675416 + 35ab20d commit 2b82ae3

File tree

6 files changed

+97
-15
lines changed

6 files changed

+97
-15
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
## 0.20.0
2+
* Add `disable_required_check!` to disable check for required options in some commands.
3+
It is a substitute of `disable_class_options` that was not working as intended.
4+
25
* Add `inject_into_module`.
36

47
## 0.19.4, release 2016-11-28

lib/thor.rb

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,6 @@ def method_option(name, options = {})
158158
end
159159
alias_method :option, :method_option
160160

161-
def disable_class_options
162-
@disable_class_options = true
163-
end
164-
165161
# Prints help information for the given command.
166162
#
167163
# ==== Parameters
@@ -329,12 +325,31 @@ def stop_on_unknown_option?(command) #:nodoc:
329325
command && stop_on_unknown_option.include?(command.name.to_sym)
330326
end
331327

328+
# Disable the check for required options for the given commands.
329+
# This is useful if you have a command that does not need the required options
330+
# to work, like help.
331+
#
332+
# ==== Parameters
333+
# Symbol ...:: A list of commands that should be affected.
334+
def disable_required_check!(*command_names)
335+
disable_required_check.merge(command_names)
336+
end
337+
338+
def disable_required_check?(command) #:nodoc:
339+
command && disable_required_check.include?(command.name.to_sym)
340+
end
341+
332342
protected
333343

334344
def stop_on_unknown_option #:nodoc:
335345
@stop_on_unknown_option ||= Set.new
336346
end
337347

348+
# help command has the required check disabled by default.
349+
def disable_required_check #:nodoc:
350+
@disable_required_check ||= Set.new([:help])
351+
end
352+
338353
# The method responsible for dispatching given the args.
339354
def dispatch(meth, given_args, given_opts, config) #:nodoc: # rubocop:disable MethodLength
340355
meth ||= retrieve_command_name(given_args)
@@ -393,12 +408,11 @@ def create_command(meth) #:nodoc:
393408
@usage ||= nil
394409
@desc ||= nil
395410
@long_desc ||= nil
396-
@disable_class_options ||= nil
397411

398412
if @usage && @desc
399413
base_class = @hide ? Thor::HiddenCommand : Thor::Command
400-
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options, @disable_class_options)
401-
@usage, @desc, @long_desc, @method_options, @hide, @disable_class_options = nil
414+
commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
415+
@usage, @desc, @long_desc, @method_options, @hide = nil
402416
true
403417
elsif all_commands[meth] || meth == "method_missing"
404418
true
@@ -480,7 +494,6 @@ def help(command = nil, subcommand = true); super; end
480494
map HELP_MAPPINGS => :help
481495

482496
desc "help [COMMAND]", "Describe available commands or one specific command"
483-
disable_class_options
484497
def help(command = nil, subcommand = false)
485498
if command
486499
if self.class.subcommands.include? command

lib/thor/base.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module Base
4242
# config<Hash>:: Configuration for this Thor class.
4343
#
4444
def initialize(args = [], local_options = {}, config = {})
45-
parse_options = config[:current_command] && config[:current_command].disable_class_options ? {} : self.class.class_options
45+
parse_options = self.class.class_options
4646

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

@@ -157,6 +158,12 @@ def stop_on_unknown_option?(command_name) #:nodoc:
157158
false
158159
end
159160

161+
# If true, option set will not suspend the execution of the command when
162+
# a required option is not provided.
163+
def disable_required_check?(command_name) #:nodoc:
164+
false
165+
end
166+
160167
# If you want only strict string args (useful when cascading thor classes),
161168
# call strict_args_position! This is disabled by default to allow dynamic
162169
# invocations.

lib/thor/command.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
class Thor
2-
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :disable_class_options, :ancestor_name)
2+
class Command < Struct.new(:name, :description, :long_description, :usage, :options, :ancestor_name)
33
FILE_REGEXP = /^#{Regexp.escape(File.dirname(__FILE__))}/
44

5-
def initialize(name, description, long_description, usage, options = nil, disable_class_options = false)
6-
super(name.to_s, description, long_description, usage, options || {}, disable_class_options)
5+
def initialize(name, description, long_description, usage, options = nil)
6+
super(name.to_s, description, long_description, usage, options || {})
77
end
88

99
def initialize_copy(other) #:nodoc:

lib/thor/parser/options.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ def self.to_switches(options)
2929
#
3030
# If +stop_on_unknown+ is true, #parse will stop as soon as it encounters
3131
# an unknown option or a regular argument.
32-
def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false)
32+
def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false)
3333
@stop_on_unknown = stop_on_unknown
34+
@disable_required_check = disable_required_check
3435
options = hash_options.values
3536
super(options)
3637

@@ -111,7 +112,7 @@ def parse(args) # rubocop:disable MethodLength
111112
end
112113
end
113114

114-
check_requirement!
115+
check_requirement! unless @disable_required_check
115116

116117
assigns = Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
117118
assigns.freeze

spec/thor_spec.rb

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,64 @@ def boring(*args)
159159
end
160160
end
161161

162+
describe "#disable_required_check!" do
163+
my_script = Class.new(Thor) do
164+
class_option "foo", :required => true
165+
166+
disable_required_check! :boring
167+
168+
desc "exec", "Run a command"
169+
def exec(*args)
170+
[options, args]
171+
end
172+
173+
desc "boring", "An ordinary command"
174+
def boring(*args)
175+
[options, args]
176+
end
177+
end
178+
179+
it "does not check the required option in the given command" do
180+
expect(my_script.start(%w(boring command))).to eq [{}, %w(command)]
181+
end
182+
183+
it "does check the required option of the remaining command" do
184+
content = capture(:stderr) { my_script.start(%w(exec command)) }
185+
expect(content).to eq "No value provided for required options '--foo'\n"
186+
end
187+
188+
it "does affects help by default" do
189+
expect(my_script.disable_required_check?(double(:name => "help"))).to be true
190+
end
191+
192+
context "when provided with multiple command names" do
193+
klass = Class.new(Thor) do
194+
disable_required_check! :foo, :bar
195+
end
196+
197+
it "affects all specified commands" do
198+
expect(klass.disable_required_check?(double(:name => "help"))).to be true
199+
expect(klass.disable_required_check?(double(:name => "foo"))).to be true
200+
expect(klass.disable_required_check?(double(:name => "bar"))).to be true
201+
expect(klass.disable_required_check?(double(:name => "baz"))).to be false
202+
end
203+
end
204+
205+
context "when invoked several times" do
206+
klass = Class.new(Thor) do
207+
disable_required_check! :foo
208+
disable_required_check! :bar
209+
end
210+
211+
it "affects all specified commands" do
212+
expect(klass.disable_required_check?(double(:name => "help"))).to be true
213+
expect(klass.disable_required_check?(double(:name => "foo"))).to be true
214+
expect(klass.disable_required_check?(double(:name => "bar"))).to be true
215+
expect(klass.disable_required_check?(double(:name => "baz"))).to be false
216+
end
217+
end
218+
end
219+
162220
describe "#map" do
163221
it "calls the alias of a method if one is provided" do
164222
expect(MyScript.start(%w(-T fish))).to eq(%w(fish))

0 commit comments

Comments
 (0)