Skip to content

Commit

Permalink
Introduce Thor2, a class with less unexpected defaults
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
MaxLap committed Sep 15, 2018
1 parent d91e8ca commit 7a292ab
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 2 deletions.
2 changes: 2 additions & 0 deletions lib/thor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -507,3 +507,5 @@ def help(command = nil, subcommand = false)
end
end
end

require "thor/thor2"
6 changes: 4 additions & 2 deletions lib/thor/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ def attr_accessor(*) #:nodoc:
end

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

# If you want to raise an error when the default value of an option does not match
# the type call check_default_type!
# This is disabled by default for compatibility.
# This is disabled by default in the Thor class for compatibility.
# This is enabled by default in the Thor2 class
def check_default_type!
@check_default_type = true
end
Expand Down
32 changes: 32 additions & 0 deletions lib/thor/thor2.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class Thor
class Thor2 < Thor
# This is a class to use instead of Thor when declaring your CLI
# This alternative works the same way as Thor, but has more common defaults:
# * If there is a failure in the argument parsing and other Thor-side
# things, the exit code will be non-zero
# * Things that look like options but are not valid options will
# will show an error of being unknown option instead of being
# used as arguments.
# * Make sure the default value of options is of the correct type
# For backward compatibility reasons, these cannot be made default in
# the regular `Thor` class
#
# This class is available in the top-level as Thor2, so you can do
# class MyCli < Thor2
# ...
# end

# Fail on unknown options instead of treating them as argument
check_unknown_options!

# Make sure the default value of options is of the correct type
check_default_type!

# All failures should result in non-zero error code
def self.exit_on_failure?
true
end
end
end

::Thor2 = Thor::Thor2
33 changes: 33 additions & 0 deletions spec/thor2_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "helper"

describe Thor2 do
my_script = Class.new(Thor2) do
class_option "verbose", :type => :boolean
class_option "mode", :type => :string

desc "checked", "a command with checked"
def checked(*args)
[options, args]
end
end

describe "#check_unknown_options!" do
it "still accept options and arguments" do
expect(my_script.start(%w[checked command --verbose])).to eq [{"verbose" => true}, %w[command]]
end

it "does not accept if non-option that looks like an option is after an argument" do
expect(capture(:stderr) do
my_script.start(%w[checked command --foo --bar])
end.strip).to eq("Unknown switches '--foo, --bar'")
end
end

it "checks the default type" do
expect do
Class.new(Thor2) do
option "bar", :type => :numeric, :default => "foo"
end
end.to raise_error(ArgumentError, "Expected numeric default value for '--bar'; got \"foo\" (string)")
end
end

0 comments on commit 7a292ab

Please sign in to comment.