lib/toys/dsl/base.rb
# frozen_string_literal: true ## # Create a base class for defining a tool with a given name. # # This method returns a base class for defining a tool with a given name. # This is useful if the naming behavior of {Toys::Tool} is not adequate for # your tool. # # ### Example # # class FooBar < Toys.Tool("Foo_Bar") # desc "This is a tool called Foo_Bar" # # def run # puts "Foo_Bar called" # end # end # # @param name [String] Name of the tool. Defaults to a name inferred from the # class name. (See {Toys::Tool}.) # @param base [Class] Use this tool class as the base class, and inherit helper # methods from it. # @param args [String,Class] Any string-valued positional argument is # interpreted as the name. Any class-valued positional argument is # interpreted as the base class. # def Toys.Tool(*args, name: nil, base: nil) # rubocop:disable Naming/MethodName args.each do |arg| case arg when ::Class raise ::ArgumentError, "Both base keyword argument and class-valud argument received" if base base = arg when ::String, ::Symbol raise ::ArgumentError, "Both name keyword argument and string-valud argument received" if name name = arg else raise ::ArgumentError, "Unrecognized argument: #{arg}" end end if base && !base.ancestors.include?(::Toys::Context) raise ::ArgumentError, "Base class must itself be a tool" end return base || ::Toys::Tool if name.nil? ::Class.new(base || ::Toys::Context) do base_class = self define_singleton_method(:inherited) do |tool_class| ::Toys::DSL::Internal.configure_class(tool_class, base_class == self ? name.to_s : nil) super(tool_class) ::Toys::DSL::Internal.setup_class_dsl(tool_class) end end end module Toys ## # Base class for defining tools # # This base class provides an alternative to the {Toys::DSL::Tool#tool} # directive for defining tools in the Toys DSL. Creating a subclass of # `Toys::Tool` will create a tool whose name is the "kebab-case" of the class # name. Subclasses can be created only in the context of a tool configuration # DSL. Furthermore, a class-defined tool can be created only at the top level # of a configuration file, or within another class-defined tool. It cannot # be a subtool of a tool block. # # ### Example # # class FooBar < Toys::Tool # desc "This is a tool called foo-bar" # # def run # puts "foo-bar called" # end # end # class Tool < Context ## # @private # def self.inherited(tool_class) DSL::Internal.configure_class(tool_class) super DSL::Internal.setup_class_dsl(tool_class) end end end