Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for nested no_commands blocks. #697

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions lib/thor/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_relative "core_ext/hash_with_indifferent_access"
require_relative "error"
require_relative "invocation"
require_relative "nested_context"
require_relative "parser"
require_relative "shell"
require_relative "line_editor"
Expand Down Expand Up @@ -418,14 +419,20 @@ def remove_command(*names)
# remove_command :this_is_not_a_command
# end
#
def no_commands
@no_commands = true
yield
ensure
@no_commands = false
def no_commands(&block)
no_commands_context.enter(&block)
end

alias_method :no_tasks, :no_commands

def no_commands_context
@no_commands_context ||= NestedContext.new
end

def no_commands?
no_commands_context.entered?
end

# Sets the namespace for the Thor or Thor::Group class. By default the
# namespace is retrieved from the class name. If your Thor class is named
# Scripts::MyScript, the help method, for example, will be called as:
Expand Down Expand Up @@ -607,7 +614,7 @@ def find_and_refresh_command(name) #:nodoc:
def inherited(klass)
super(klass)
Thor::Base.register_klass_file(klass)
klass.instance_variable_set(:@no_commands, false)
klass.instance_variable_set(:@no_commands, 0)
end

# Fire this callback whenever a method is added. Added methods are
Expand All @@ -624,8 +631,7 @@ def method_added(meth)
# Return if it's not a public instance method
return unless public_method_defined?(meth.to_sym)

@no_commands ||= false
return if @no_commands || !create_command(meth)
return if no_commands? || !create_command(meth)

is_thor_reserved_word?(meth, :command)
Thor::Base.register_klass_file(self)
Expand Down
29 changes: 29 additions & 0 deletions lib/thor/nested_context.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Thor
class NestedContext
def initialize
@depth = 0
end

def enter
push

yield
ensure
pop
end

def entered?
@depth > 0
end

private

def push
@depth += 1
end

def pop
@depth -= 1
end
end
end
1 change: 1 addition & 0 deletions spec/base_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def hello
it "avoids methods being added as commands" do
expect(MyScript.commands.keys).to include("animal")
expect(MyScript.commands.keys).not_to include("this_is_not_a_command")
expect(MyScript.commands.keys).not_to include("neither_is_this")
end
end

Expand Down
7 changes: 6 additions & 1 deletion spec/fixtures/script.thor
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ class MyScript < Thor
desc "animal TYPE", "horse around"

no_commands do
def this_is_not_a_command
no_commands do
def this_is_not_a_command
end
end

def neither_is_this
end
end

Expand Down
20 changes: 20 additions & 0 deletions spec/nested_context_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require "helper"

describe Thor::NestedContext do
subject(:context) { described_class.new }

describe "#enter" do
it "is never empty within the entered block" do
context.enter do
context.enter {}

expect(context).to be_entered
end
end

it "is empty when outside of all blocks" do
context.enter { context.enter {} }
expect(context).not_to be_entered
end
end
end