module Boson # A library is a group of commands (Command objects) usually grouped together # by a module. Libraries are loaded from different sources depending on the # library subclass. # # === Creating Your Own Library # To create your own subclass you need to define what sources the subclass can # handle with handles(). See Loader to see what instance methods to override # for a subclass. class Library include Loader class <<self attr_accessor :handle_blocks # Returns true when the subclass is chosen to load. def handles(&block) (Library.handle_blocks ||= []) << [self,block] end end # Public attributes for use outside of Boson. ATTRIBUTES = [:commands, :loaded, :module, :name] attr_reader *(ATTRIBUTES + [:commands_hash, :library_file]) # Private attribute for use within Boson. attr_reader :new_module, :new_commands, :lib_file # Creates a library object with the given hash. Each hash pair maps # directly to an instance variable and value. Defaults for attributes are # read from config[:libraries][@library_name][@attribute]. # # @param [Hash] hash # @option hash [String] :name Required attribute # @option hash [Array,Hash] :commands Commands belonging to a library. A # hash configures command attributes for the given commands with command # names pointing to their configs. See Command.new for a command's # configurable attributes. If an array, the commands are set for the # given library, overidding default command detection. Example: # :commands=>{'commands'=>{:desc=>'Lists commands', :alias=>'com'}} # @option hash [Boolean] :force Forces a library to ignore when a library's # methods are overriding existing ones. Use with caution. Default is false. def initialize(hash) before_initialize @name = set_name(hash.delete(:name)) or raise ArgumentError, "Library missing required key :name" @loaded = false @commands_hash = {} @commands = [] set_config (config[:libraries][@name] || {}).merge(hash), true set_command_aliases(config[:command_aliases]) end # A concise symbol version of a library type i.e. FileLibrary -> :file. def library_type str = self.class.to_s[/::(\w+)Library$/, 1] || 'library' str.downcase.to_sym end # handles names under directories def clean_name @name[/\w+$/] end # sets name def set_name(name) name.to_s end module API # The object a library uses for executing its commands. def namespace_object @namespace_object ||= Boson.main_object end # Method hook called at the beginning of initialize def before_initialize end # Determines if library is local i.e. scoped to current directory/project def local? false end # @return [Hash] Attributes used internally by a library. Defaults to # using Boson.config but can be overridden to be library-specific. def config Boson.config end end include API # Command objects of library's commands def command_objects(names=self.commands, command_array=Boson.commands) command_array.select {|e| names.include?(e.name) && e.lib == self.name } end # Command object for given command name def command_object(name) command_objects([name])[0] end private def set_attributes(hash, force=false) hash.each do |k,v| if instance_variable_get("@#{k}").nil? || force instance_variable_set("@#{k}", v) end end end def set_config(config, force=false) if (commands = config.delete(:commands)) if commands.is_a?(Array) @commands += commands @pre_defined_commands = true elsif commands.is_a?(Hash) @commands += commands.keys @commands_hash = Util.recursive_hash_merge commands, @commands_hash end end set_command_aliases config.delete(:command_aliases) if config[:command_aliases] set_attributes config, force end def set_command_aliases(command_aliases) (command_aliases || {}).each do |cmd, cmd_alias| @commands_hash[cmd] ||= {} @commands_hash[cmd][:alias] ||= cmd_alias end end end end