Skip to content

Commit 21d1aaa

Browse files
committed
Introduce Thor2, a class with less unexpected defaults
This new class allows having more expected defaults without breaking backward compatibility. Documentation can then recommend using Thor2 for new CLIs which will be more intuitive for users.
1 parent de10e38 commit 21d1aaa

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

lib/thor.rb

+2
Original file line numberDiff line numberDiff line change
@@ -507,3 +507,5 @@ def help(command = nil, subcommand = false)
507507
end
508508
end
509509
end
510+
511+
require "thor/thor2"

lib/thor/base.rb

+4-2
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ def attr_accessor(*) #:nodoc:
138138
end
139139

140140
# If you want to raise an error for unknown options, call check_unknown_options!
141-
# This is disabled by default to allow dynamic invocations.
141+
# This is disabled by default in the Thor class to allow dynamic invocations.
142+
# This is enabled by default in the Thor2 class
142143
def check_unknown_options!
143144
@check_unknown_options = true
144145
end
@@ -153,7 +154,8 @@ def check_unknown_options?(config) #:nodoc:
153154

154155
# If you want to raise an error when the default value of an option does not match
155156
# the type call check_default_type!
156-
# This is disabled by default for compatibility.
157+
# This is disabled by default in the Thor class for compatibility.
158+
# This is enabled by default in the Thor2 class
157159
def check_default_type!
158160
@check_default_type = true
159161
end

lib/thor/thor2.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Thor
2+
class Thor2 < Thor
3+
# This is a class to use instead of Thor when declaring your CLI
4+
# This alternative works the same way as Thor, but has more common defaults:
5+
# * If there is a failure in the argument parsing and other Thor-side
6+
# things, the exit code will be non-zero
7+
# * Things that look like options but are not valid options will
8+
# will show an error of being unknown option instead of being
9+
# used as arguments.
10+
# * Make sure the default value of options is of the correct type
11+
# For backward compatibility reasons, these cannot be made default in
12+
# the regular `Thor` class
13+
#
14+
# This class is available in the top-level as Thor2, so you can do
15+
# class MyCli < Thor2
16+
# ...
17+
# end
18+
19+
# Fail on unknown options instead of treating them as argument
20+
check_unknown_options!
21+
22+
# Make sure the default value of options is of the correct type
23+
check_default_type!
24+
25+
# All failures should result in non-zero error code
26+
def self.exit_on_failure?
27+
true
28+
end
29+
end
30+
end
31+
32+
::Thor2 = Thor::Thor2

spec/fixtures/thor2.thor

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
require "thor"
2+
3+
class MySimpleThor2 < Thor2
4+
class_option "verbose", :type => :boolean
5+
class_option "mode", :type => :string
6+
7+
desc "checked", "a command with checked"
8+
def checked(*args)
9+
puts [options, args].inspect
10+
[options, args]
11+
end
12+
end
13+
14+
MySimpleThor2.start(ARGV)
15+

spec/thor2_spec.rb

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
require "helper"
2+
3+
describe Thor2 do
4+
describe "#check_unknown_options!" do
5+
it "still accept options and arguments" do
6+
stdout, _, status = run_thor_fixture_standalone('thor2', %w(checked command --verbose))
7+
8+
expect(stdout.strip).to eq [{"verbose" => true}, %w[command]].inspect
9+
expect(status.exitstatus).to eq(0)
10+
end
11+
12+
it "does not accept if non-option that looks like an option is after an argument and exits with code 1" do
13+
_stdout, stderr, status = run_thor_fixture_standalone('thor2', %w(checked command --foo --bar))
14+
expect(stderr.strip).to eq("Unknown switches '--foo, --bar'")
15+
expect(status.exitstatus).to eq(1)
16+
end
17+
end if RUBY_VERSION > "1.8.7"
18+
19+
it "checks the default type" do
20+
expect do
21+
Class.new(Thor2) do
22+
option "bar", :type => :numeric, :default => "foo"
23+
end
24+
end.to raise_error(ArgumentError, "Expected numeric default value for '--bar'; got \"foo\" (string)")
25+
end
26+
end

0 commit comments

Comments
 (0)