Skip to content

Commit

Permalink
Merge pull request #263 from twinturbo/subcommand-fixes
Browse files Browse the repository at this point in the history
Subcommand fixes (Close #241)
  • Loading branch information
wycats committed Oct 18, 2012
2 parents b5cf68d + e2b3ff4 commit 976de90
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
22 changes: 19 additions & 3 deletions lib/thor.rb
Expand Up @@ -210,7 +210,7 @@ def subcommand(subcommand, subcommand_class)

define_method(subcommand) do |*args|
args, opts = Thor::Arguments.split(args)
invoke subcommand_class, args, opts
invoke subcommand_class, args, opts, :invoked_via_subcommand => true
end
end

Expand Down Expand Up @@ -255,8 +255,24 @@ def check_unknown_options?(config) #:nodoc:

# The method responsible for dispatching given the args.
def dispatch(meth, given_args, given_opts, config) #:nodoc:
meth ||= retrieve_task_name(given_args)
task = all_tasks[normalize_task_name(meth)]
# There is an edge case when dispatching from a subcommand.
# A problem occurs invoking the default task. This case occurs
# when arguments are passed and a default task is defined, and
# the first given_args does not match the default task.
# Thor use "help" by default so we skip that case.
# Note the call to retrieve_task_name. It's called with
# given_args.dup since that method calls args.shift. Then lookup
# the task normally. If the first item in given_args is not
# a task then use the default task. The given_args will be
# intact later since dup was used.
if config[:invoked_via_subcommand] && given_args.size >= 1 && default_task != "help" && given_args.first != default_task
meth ||= retrieve_task_name(given_args.dup)
task = all_tasks[normalize_task_name(meth)]
task ||= all_tasks[normalize_task_name(default_task)]
else
meth ||= retrieve_task_name(given_args)
task = all_tasks[normalize_task_name(meth)]
end

if task
args, opts = Thor::Options.split(given_args)
Expand Down
62 changes: 62 additions & 0 deletions spec/register_spec.rb
Expand Up @@ -54,6 +54,34 @@ def animal
end
end

class PluginWithDefault < Thor
desc "say MSG", "print MSG"
def say(msg)
puts msg
end

default_task :say
end

class PluginWithDefaultMultipleArguments < Thor
desc "say MSG [MSG]", "print multiple messages"
def say(*args)
puts args
end

default_task :say
end

class PluginWithDefaultTaskAndDeclaredArgument < Thor
desc "say MSG [MSG]", "print multiple messages"
argument :msg
def say
puts msg
end

default_task :say
end

BoringVendorProvidedCLI.register(
ExcitingPluginCLI,
"exciting",
Expand All @@ -79,6 +107,24 @@ def animal
"zoo [-w animal]",
"Shows a provided animal or just zebra")

BoringVendorProvidedCLI.register(
PluginWithDefault,
'say',
'say message',
'subcommands ftw')

BoringVendorProvidedCLI.register(
PluginWithDefaultMultipleArguments,
'say_multiple',
'say message',
'subcommands ftw')

BoringVendorProvidedCLI.register(
PluginWithDefaultTaskAndDeclaredArgument,
'say_argument',
'say message',
'subcommands ftw')

describe ".register-ing a Thor subclass" do
it "registers the plugin as a subcommand" do
fireworks_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting fireworks]) }
Expand All @@ -90,6 +136,22 @@ def animal
expect(help_output).to include('do exciting things')
end

it "invokes the default task correctly" do
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say hello]) }
expect(output).to include("hello")
end

it "invokes the default task correctly with multiple args" do
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_multiple hello adam]) }
expect(output).to include("hello")
expect(output).to include("adam")
end

it "invokes the default task correctly with a declared argument" do
output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_argument hello]) }
expect(output).to include("hello")
end

context "when $thor_runner is false" do
it "includes the plugin's subcommand name in subcommand's help" do
begin
Expand Down

0 comments on commit 976de90

Please sign in to comment.