diff --git a/lib/thor.rb b/lib/thor.rb index cf999e6e..f2bdad00 100644 --- a/lib/thor.rb +++ b/lib/thor.rb @@ -439,6 +439,17 @@ def disable_required_check?(command) #:nodoc: command && disable_required_check.include?(command.name.to_sym) end + # Checks if a specified command exists. + # + # ==== Parameters + # command_name:: The name of the command to check for existence. + # + # ==== Returns + # Boolean:: +true+ if the command exists, +false+ otherwise. + def command_exists?(command_name) + commands.keys.include?(normalize_command_name(command_name)) + end + protected # Returns this class exclusive options array set. diff --git a/lib/thor/group.rb b/lib/thor/group.rb index 263ccfe6..aaadfa50 100644 --- a/lib/thor/group.rb +++ b/lib/thor/group.rb @@ -211,6 +211,17 @@ def handle_argument_error(command, error, _args, arity) #:nodoc: raise error, msg end + # Checks if a specified command exists. + # + # ==== Parameters + # command_name:: The name of the command to check for existence. + # + # ==== Returns + # Boolean:: +true+ if the command exists, +false+ otherwise. + def command_exists?(command_name) + commands.keys.include?(command_name) + end + protected # The method responsible for dispatching given the args. diff --git a/spec/fixtures/script.thor b/spec/fixtures/script.thor index 92fb0cb0..2fbdd097 100644 --- a/spec/fixtures/script.thor +++ b/spec/fixtures/script.thor @@ -264,12 +264,15 @@ end class Apple < Thor namespace :fruits desc 'apple', 'apple'; def apple; end + desc 'rotten-apple', 'rotten apple'; def rotten_apple; end + map "ra" => :rotten_apple end class Pear < Thor namespace :fruits desc 'pear', 'pear'; def pear; end end + class MyClassOptionScript < Thor class_option :free diff --git a/spec/group_spec.rb b/spec/group_spec.rb index 6d5a65ee..b308c914 100644 --- a/spec/group_spec.rb +++ b/spec/group_spec.rb @@ -186,6 +186,16 @@ end end + describe "#command_exists?" do + it "returns true for a command that is defined in the class" do + expect(MyCounter.command_exists?("one")).to be true + end + + it "returns false for a command that is not defined in the class" do + expect(MyCounter.command_exists?("zero")).to be false + end + end + describe "edge-cases" do it "can handle boolean options followed by arguments" do klass = Class.new(Thor::Group) do diff --git a/spec/thor_spec.rb b/spec/thor_spec.rb index 6d03eb41..f9fd0fe0 100644 --- a/spec/thor_spec.rb +++ b/spec/thor_spec.rb @@ -340,6 +340,18 @@ def self.exit_on_failure? end end + describe "#command_exists?" do + it "returns true for a command that is defined in the class" do + expect(MyScript.command_exists?("zoo")).to be true + expect(MyScript.command_exists?("name-with-dashes")).to be true + expect(MyScript.command_exists?("animal_prison")).to be true + end + + it "returns false for a command that is not defined in the class" do + expect(MyScript.command_exists?("animal_heaven")).to be false + end + end + describe "#map" do it "calls the alias of a method if one is provided" do expect(MyScript.start(%w(-T fish))).to eq(%w(fish))