summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/coderay/helpers/plugin.rb643
1 files changed, 330 insertions, 313 deletions
diff --git a/lib/coderay/helpers/plugin.rb b/lib/coderay/helpers/plugin.rb
index ba62983..ada5ae7 100644
--- a/lib/coderay/helpers/plugin.rb
+++ b/lib/coderay/helpers/plugin.rb
@@ -1,350 +1,367 @@
module CodeRay
-# = PluginHost
-#
-# A simple subclass plugin system.
-#
-# Example:
-# class Generators < PluginHost
-# plugin_path 'app/generators'
-# end
-#
-# class Generator
-# extend Plugin
-# PLUGIN_HOST = Generators
-# end
-#
-# class FancyGenerator < Generator
-# register_for :fancy
-# end
-#
-# Generators[:fancy] #-> FancyGenerator
-# # or
-# CodeRay.require_plugin 'Generators/fancy'
-module PluginHost
-
- # Raised if Encoders::[] fails because:
- # * a file could not be found
- # * the requested Encoder is not registered
- PluginNotFound = Class.new Exception
- HostNotFound = Class.new Exception
-
- PLUGIN_HOSTS = []
- PLUGIN_HOSTS_BY_ID = {} # dummy hash
-
- # Loads all plugins using list and load.
- def load_all
- for plugin in list
- load plugin
- end
- end
-
- # Returns the Plugin for +id+.
+ # = PluginHost
+ #
+ # A simple subclass/subfolder plugin system.
#
# Example:
- # yaml_plugin = MyPluginHost[:yaml]
- def [] id, *args, &blk
- plugin = validate_id(id)
- begin
- plugin = plugin_hash.[] plugin, *args, &blk
- end while plugin.is_a? Symbol
- plugin
- end
-
- # Alias for +[]+.
- alias load []
-
- def require_helper plugin_id, helper_name
- path = path_to File.join(plugin_id, helper_name)
- require path
- end
-
- class << self
-
- # Adds the module/class to the PLUGIN_HOSTS list.
- def extended mod
- PLUGIN_HOSTS << mod
+ # class Generators < PluginHost
+ # plugin_path 'app/generators'
+ # end
+ #
+ # class Generator
+ # extend Plugin
+ # PLUGIN_HOST = Generators
+ # end
+ #
+ # class FancyGenerator < Generator
+ # register_for :fancy
+ # end
+ #
+ # Generators[:fancy] #-> FancyGenerator
+ # # or
+ # CodeRay.require_plugin 'Generators/fancy'
+ # # or
+ # Generators::Fancy
+ module PluginHost
+
+ # Raised if Encoders::[] fails because:
+ # * a file could not be found
+ # * the requested Plugin is not registered
+ PluginNotFound = Class.new LoadError
+ HostNotFound = Class.new LoadError
+
+ PLUGIN_HOSTS = []
+ PLUGIN_HOSTS_BY_ID = {} # dummy hash
+
+ # Loads all plugins using list and load.
+ def load_all
+ for plugin in list
+ load plugin
+ end
end
-
- # Warns you that you should not #include this module.
- def included mod
- warn "#{name} should not be included. Use extend."
+
+ # Returns the Plugin for +id+.
+ #
+ # Example:
+ # yaml_plugin = MyPluginHost[:yaml]
+ def [] id, *args, &blk
+ plugin = validate_id(id)
+ begin
+ plugin = plugin_hash.[] plugin, *args, &blk
+ end while plugin.is_a? Symbol
+ plugin
+ end
+
+ alias load []
+
+ # Tries to +load+ the missing plugin by translating +const+ to the
+ # underscore form (eg. LinesOfCode becomes lines_of_code).
+ def const_missing const
+ id = const.to_s.
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
+ downcase
+ load id
end
-
- # Find the PluginHost for host_id.
- def host_by_id host_id
- unless PLUGIN_HOSTS_BY_ID.default_proc
- ph = Hash.new do |h, a_host_id|
- for host in PLUGIN_HOSTS
- h[host.host_id] = host
+
+ # Loads a helper file for the given +plugin_id+ and +helper_name+.
+ # Helpers are located in a folder with the name of the plugin,
+ # so if you have a plugin called "plugin" inside a folder named "plugins"
+ # and a helper named "helper", this method will try to load
+ # "plugins/plugin/helper".
+ def require_helper plugin_id, helper_name
+ path = path_to File.join(plugin_id, helper_name)
+ require path
+ end
+
+ class << self
+
+ # Adds the module/class to the PLUGIN_HOSTS list.
+ def extended mod
+ PLUGIN_HOSTS << mod
+ end
+
+ # Warns you that you should not #include this module.
+ def included mod
+ warn "#{name} should not be included. Use extend."
+ end
+
+ # Find the PluginHost for host_id.
+ def host_by_id host_id
+ unless PLUGIN_HOSTS_BY_ID.default_proc
+ ph = Hash.new do |h, a_host_id|
+ for host in PLUGIN_HOSTS
+ h[host.host_id] = host
+ end
+ h.fetch a_host_id, nil
end
- h.fetch a_host_id, nil
+ PLUGIN_HOSTS_BY_ID.replace ph
end
- PLUGIN_HOSTS_BY_ID.replace ph
+ PLUGIN_HOSTS_BY_ID[host_id]
end
- PLUGIN_HOSTS_BY_ID[host_id]
+
end
-
- end
-
- # The path where the plugins can be found.
- def plugin_path *args
- unless args.empty?
- @plugin_path = File.expand_path File.join(*args)
- load_map
+
+ # The path where the plugins can be found.
+ def plugin_path *args
+ unless args.empty?
+ @plugin_path = File.expand_path File.join(*args)
+ load_map
+ end
+ @plugin_path
end
- @plugin_path
- end
-
- # The host's ID.
- #
- # If PLUGIN_HOST_ID is not set, it is simply the class name.
- def host_id
- if self.const_defined? :PLUGIN_HOST_ID
- self::PLUGIN_HOST_ID
- else
- name
+
+ # The host's ID.
+ #
+ # If PLUGIN_HOST_ID is not set, it is simply the class name.
+ def host_id
+ if self.const_defined? :PLUGIN_HOST_ID
+ self::PLUGIN_HOST_ID
+ else
+ name
+ end
end
- end
-
- # Map a plugin_id to another.
- #
- # Usage: Put this in a file plugin_path/_map.rb.
- #
- # class MyColorHost < PluginHost
- # map :navy => :dark_blue,
- # :maroon => :brown,
- # :luna => :moon
- # end
- def map hash
- for from, to in hash
- from = validate_id from
- to = validate_id to
- plugin_hash[from] = to unless plugin_hash.has_key? from
+
+ # Map a plugin_id to another.
+ #
+ # Usage: Put this in a file plugin_path/_map.rb.
+ #
+ # class MyColorHost < PluginHost
+ # map :navy => :dark_blue,
+ # :maroon => :brown,
+ # :luna => :moon
+ # end
+ def map hash
+ for from, to in hash
+ from = validate_id from
+ to = validate_id to
+ plugin_hash[from] = to unless plugin_hash.has_key? from
+ end
end
- end
-
- # Define the default plugin to use when no plugin is found
- # for a given id.
- #
- # See also map.
- #
- # class MyColorHost < PluginHost
- # map :navy => :dark_blue
- # default :gray
- # end
- def default id = nil
- if id
- id = validate_id id
- plugin_hash[nil] = id
- else
- plugin_hash[nil]
+
+ # Define the default plugin to use when no plugin is found
+ # for a given id.
+ #
+ # See also map.
+ #
+ # class MyColorHost < PluginHost
+ # map :navy => :dark_blue
+ # default :gray
+ # end
+ def default id = nil
+ if id
+ id = validate_id id
+ plugin_hash[nil] = id
+ else
+ plugin_hash[nil]
+ end
end
- end
-
- # Every plugin must register itself for one or more
- # +ids+ by calling register_for, which calls this method.
- #
- # See Plugin#register_for.
- def register plugin, *ids
- for id in ids
- unless id.is_a? Symbol
- raise ArgumentError,
- "id must be a Symbol, but it was a #{id.class}"
+
+ # Every plugin must register itself for one or more
+ # +ids+ by calling register_for, which calls this method.
+ #
+ # See Plugin#register_for.
+ def register plugin, *ids
+ for id in ids
+ unless id.is_a? Symbol
+ raise ArgumentError,
+ "id must be a Symbol, but it was a #{id.class}"
+ end
+ plugin_hash[validate_id(id)] = plugin
end
- plugin_hash[validate_id(id)] = plugin
end
- end
-
- # A Hash of plugion_id => Plugin pairs.
- def plugin_hash
- @plugin_hash ||= create_plugin_hash
- end
-
- # Returns an array of all .rb files in the plugin path.
- #
- # The extension .rb is not included.
- def list
- Dir[path_to('*')].select do |file|
- File.basename(file)[/^(?!_)\w+\.rb$/]
- end.map do |file|
- File.basename file, '.rb'
+
+ # A Hash of plugion_id => Plugin pairs.
+ def plugin_hash
+ @plugin_hash ||= create_plugin_hash
end
- end
-
- # Makes a map of all loaded plugins.
- def inspect
- map = plugin_hash.dup
- map.each do |id, plugin|
- map[id] = plugin.to_s[/(?>\w+)$/]
+
+ # Returns an array of all .rb files in the plugin path.
+ #
+ # The extension .rb is not included.
+ def list
+ Dir[path_to('*')].select do |file|
+ File.basename(file)[/^(?!_)\w+\.rb$/]
+ end.map do |file|
+ File.basename file, '.rb'
+ end
end
- "#{name}[#{host_id}]#{map.inspect}"
- end
-
-protected
- # Created a new plugin list and stores it to @plugin_hash.
- def create_plugin_hash
- @plugin_hash =
- Hash.new do |h, plugin_id|
- id = validate_id(plugin_id)
- path = path_to id
- begin
- require path
- rescue LoadError => boom
- if h.has_key? nil # default plugin
- h[id] = h[nil]
+
+ # Makes a map of all loaded plugins.
+ def inspect
+ map = plugin_hash.dup
+ map.each do |id, plugin|
+ map[id] = plugin.to_s[/(?>\w+)$/]
+ end
+ "#{name}[#{host_id}]#{map.inspect}"
+ end
+
+ protected
+ # Created a new plugin list and stores it to @plugin_hash.
+ def create_plugin_hash
+ @plugin_hash =
+ Hash.new do |h, plugin_id|
+ id = validate_id(plugin_id)
+ path = path_to id
+ begin
+ require path
+ rescue LoadError => boom
+ if h.has_key? nil # default plugin
+ h[id] = h[nil]
+ else
+ raise PluginNotFound, 'Could not load plugin %p: %s' % [id, boom]
+ end
else
- raise PluginNotFound, 'Could not load plugin %p: %s' % [id, boom]
- end
- else
- # Plugin should have registered by now
- unless h.has_key? id
- raise PluginNotFound,
- "No #{self.name} plugin for #{id.inspect} found in #{path}."
+ # Plugin should have registered by now
+ unless h.has_key? id
+ raise PluginNotFound,
+ "No #{self.name} plugin for #{id.inspect} found in #{path}."
+ end
end
+ h[id]
end
- h[id]
+ end
+
+ # Loads the map file (see map).
+ #
+ # This is done automatically when plugin_path is called.
+ def load_map
+ mapfile = path_to '_map'
+ if File.exist? mapfile
+ require mapfile
+ elsif $VERBOSE
+ warn 'no _map.rb found for %s' % name
end
- end
-
- # Loads the map file (see map).
- #
- # This is done automatically when plugin_path is called.
- def load_map
- mapfile = path_to '_map'
- if File.exist? mapfile
- require mapfile
- elsif $VERBOSE
- warn 'no _map.rb found for %s' % name
end
- end
-
- # Returns the Plugin for +id+.
- # Use it like Hash#fetch.
- #
- # Example:
- # yaml_plugin = MyPluginHost[:yaml, :default]
- def fetch id, *args, &blk
- plugin_hash.fetch validate_id(id), *args, &blk
- end
-
- # Returns the expected path to the plugin file for the given id.
- def path_to plugin_id
- File.join plugin_path, "#{plugin_id}.rb"
- end
-
- # Converts +id+ to a Symbol if it is a String,
- # or returns +id+ if it already is a Symbol.
- #
- # Raises +ArgumentError+ for all other objects, or if the
- # given String includes non-alphanumeric characters (\W).
- def validate_id id
- if id.is_a? Symbol or id.nil?
- id
- elsif id.is_a? String
- if id[/\w+/] == id
- id.downcase.to_sym
+
+ # Returns the Plugin for +id+.
+ # Use it like Hash#fetch.
+ #
+ # Example:
+ # yaml_plugin = MyPluginHost[:yaml, :default]
+ def fetch id, *args, &blk
+ plugin_hash.fetch validate_id(id), *args, &blk
+ end
+
+ # Returns the expected path to the plugin file for the given id.
+ def path_to plugin_id
+ File.join plugin_path, "#{plugin_id}.rb"
+ end
+
+ # Converts +id+ to a Symbol if it is a String,
+ # or returns +id+ if it already is a Symbol.
+ #
+ # Raises +ArgumentError+ for all other objects, or if the
+ # given String includes non-alphanumeric characters (\W).
+ def validate_id id
+ if id.is_a? Symbol or id.nil?
+ id
+ elsif id.is_a? String
+ if id[/\w+/] == id
+ id.downcase.to_sym
+ else
+ warn "Invalid id: '#{id}' given."
+ ''
+ end
else
- raise ArgumentError, "Invalid id: '#{id}' given."
+ raise ArgumentError,
+ "String or Symbol expected, but #{id.class} given."
end
- else
- raise ArgumentError,
- "String or Symbol expected, but #{id.class} given."
end
- end
-
-end
-
-
-# = Plugin
-#
-# Plugins have to include this module.
-#
-# IMPORTANT: use extend for this module.
-#
-# Example: see PluginHost.
-module Plugin
-
- def included mod
- warn "#{name} should not be included. Use extend."
- end
-
- # Register this class for the given langs.
- # Example:
- # class MyPlugin < PluginHost::BaseClass
- # register_for :my_id
- # ...
- # end
- #
- # See PluginHost.register.
- def register_for *ids
- @plugin_id = ids.first
- plugin_host.register self, *ids
+
end
- # Returns the title of the plugin, or sets it to the
- # optional argument +title+.
- def title title = nil
- if title
- @title = title.to_s
- else
- @title ||= name[/([^:]+)$/, 1]
- end
- end
-
- # The host for this Plugin class.
- def plugin_host host = nil
- if host and not host.is_a? PluginHost
- raise ArgumentError,
- "PluginHost expected, but #{host.class} given."
- end
- self.const_set :PLUGIN_HOST, host if host
- self::PLUGIN_HOST
- end
-
- # Require some helper files.
+
+ # = Plugin
#
- # Example:
+ # Plugins have to include this module.
#
- # class MyPlugin < PluginHost::BaseClass
- # register_for :my_id
- # helper :my_helper
+ # IMPORTANT: use extend for this module.
#
- # The above example loads the file myplugin/my_helper.rb relative to the
- # file in which MyPlugin was defined.
- #
- # You can also load a helper from a different plugin:
- #
- # helper 'other_plugin/helper_name'
- def helper *helpers
- for helper in helpers
- if helper.is_a?(String) && helper[/\//]
- self::PLUGIN_HOST.require_helper $`, $'
+ # See CodeRay::PluginHost for examples.
+ module Plugin
+
+ def included mod # :nodoc:
+ warn "#{name} should not be included. Use extend."
+ end
+
+ # Register this class for the given langs.
+ # Example:
+ # class MyPlugin < PluginHost::BaseClass
+ # register_for :my_id
+ # ...
+ # end
+ #
+ # See PluginHost.register.
+ def register_for *ids
+ @plugin_id = ids.first
+ plugin_host.register self, *ids
+ end
+
+ # Returns the title of the plugin, or sets it to the
+ # optional argument +title+.
+ def title title = nil
+ if title
+ @title = title.to_s
else
- self::PLUGIN_HOST.require_helper plugin_id.to_s, helper.to_s
+ @title ||= name[/([^:]+)$/, 1]
end
end
+
+ # The PluginHost for this Plugin class.
+ def plugin_host host = nil
+ if host and not host.is_a? PluginHost
+ raise ArgumentError,
+ "PluginHost expected, but #{host.class} given."
+ end
+ self.const_set :PLUGIN_HOST, host if host
+ self::PLUGIN_HOST
+ end
+
+ # Require some helper files.
+ #
+ # Example:
+ #
+ # class MyPlugin < PluginHost::BaseClass
+ # register_for :my_id
+ # helper :my_helper
+ #
+ # The above example loads the file myplugin/my_helper.rb relative to the
+ # file in which MyPlugin was defined.
+ #
+ # You can also load a helper from a different plugin:
+ #
+ # helper 'other_plugin/helper_name'
+ def helper *helpers
+ for helper in helpers
+ if helper.is_a?(String) && helper[/\//]
+ self::PLUGIN_HOST.require_helper $`, $'
+ else
+ self::PLUGIN_HOST.require_helper plugin_id.to_s, helper.to_s
+ end
+ end
+ end
+
+ # Returns the plugin id used by the engine.
+ def plugin_id
+ @plugin_id || name[/\w+$/].downcase
+ end
+
end
-
- # Returns the pulgin id used by the engine.
- def plugin_id
- @plugin_id || name[/\w+$/].downcase
+
+ # Convenience method for plugin loading.
+ # The syntax used is:
+ #
+ # CodeRay.require_plugin '<Host ID>/<Plugin ID>'
+ #
+ # Returns the loaded plugin.
+ def self.require_plugin path
+ host_id, plugin_id = path.split '/', 2
+ host = PluginHost.host_by_id(host_id)
+ raise PluginHost::HostNotFound,
+ "No host for #{host_id.inspect} found." unless host
+ host.load plugin_id
end
-
-end
-
-# Convenience method for plugin loading.
-# The syntax used is:
-#
-# CodeRay.require_plugin '<Host ID>/<Plugin ID>'
-#
-# Returns the loaded plugin.
-def self.require_plugin path
- host_id, plugin_id = path.split '/', 2
- host = PluginHost.host_by_id(host_id)
- raise PluginHost::HostNotFound,
- "No host for #{host_id.inspect} found." unless host
- host.load plugin_id
-end
-
+
end \ No newline at end of file