/tg-plugins

Class definitions for generic Plugin and PluginManager

Primary LanguageRubyOtherNOASSERTION

TG-Plugins

Plugin system for Ruby projects.

This consists of a Plugin module, which can be extended in any Ruby class that is to be used as a plugin, and a PluginManager class, which can be used to manage (find, load, unload, list, execute) plugins.

The Plugin module uses ad-hoc decorators (actually class methods, once mixed in) to define metadata describing the plugin:

  • name
  • version
  • canon_name - the name and version number of the plugin
  • author
  • license
  • description - human-readable description of the plugin
  • help - a help page or manual for the plugin

An application defines "specifications" for operations that can be performed by multiple plugins. A specification includes a unique name (Symbol), a human-readable prototype string, an Array of arguments classes, and an output class. A plugin can map one of its methods to a specification, supplying a confidence rating that reflects its ability to implement that specification. The confidence rating can be unconditional, or can be determined based on specific input.

For example:

  require 'tg/plugin'
  class ImageProcessingApplication
    def initialize(args)
      TG::Plugin::Specification.new( :load_image_file, 
                                     'Graphic load_image_file(String|IO)',
                                     [ [String, IO] ], Graphic )
    end
  end

  class PngImage
    extend TG::Plugin
    name 'PNG Image Support'
    version '1.0.1'

    def load_file(file)
      obj = graphics_obj_from_file(file)
      return obj
    end
    spec :load_image_file, :load_file do |f|
      # ... code to evaluate to 100 if f is a PNG, 0 otherwise ...
    end
  end    

  class NullImage
    extend TG::Plugin
    name 'NULL Image Handler'
    version '0.9'

    def load_file(file)
      $stderr.puts "Unrecognized Image: #{file.inspect}" if $debug 
      return Graphic.null_image()
    end
    # unconditionally return a rating of 10
    spec :load_image_file, :load_file, 10
  end    

Note that Arrays in a Specification argument list are used to implement OR: the element "[String, Array]" in the arguments array means that the argument in that position can be either a String or Array. This can also be used in the return-type, so that a plugin can be declared to return "[TrueClass, FalseClass]" (true or false), "[String, NilClass]" (string or nil), etc. To specify "any class", use Object as the argument/return-value class.

The PluginManager will find the fittest Plugin to handle a given input:

  require 'tg/plugin_mgr'
  # initialize PluginManager and load plugins
  TG::PluginManager.add_base_dir( './plugins' )
  TG::PluginManager.app_init_and_startup

  # find fittest 'load_image_path' plugin for contents of 'path'
  TG::PluginManager.fittest_providing(:load_image_file, path) do |plugin|
    plugin.spec_invoke(:load_image_file, path)
  end

This will query all plugins that provide a method implementing the load_image_file specification, calling the confidence-rating block (the block argument to the spec() call) of each. The plugin which returns the highest confidence rating (generally in the range 0-100, though this is not enforced and can be application-specific) is then returned or passed to a block (if provided).

The PluginManager also defines the fittest_invoke() method, which calls fittest_providing() to get the plugin, then invokes the plugin method implementing the specification on the input.

More detail is provided in the rdoc strings.

License

https://github.com/mkfs/pogo-license This is the standard BSD 3-clause license with a 4th clause added to prohibit non-collaborative communication with project developers.