| Module | CodeRay::PluginHost |
| In: |
lib/coderay/helpers/plugin.rb
|
A simple subclass/subfolder plugin system.
Example:
class Generators extend 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
Tries to load the missing plugin by translating const to the underscore form (eg. LinesOfCode becomes lines_of_code).
# File lib/coderay/helpers/plugin.rb, line 61
61: def const_missing const
62: id = const.to_s.
63: gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
64: gsub(/([a-z\d])([A-Z])/,'\1_\2').
65: downcase
66: load id
67: end
Define the default plugin to use when no plugin is found for a given id, or return the default plugin.
See also map.
class MyColorHost < PluginHost map :navy => :dark_blue default :gray end MyColorHost.default # loads and returns the Gray plugin
# File lib/coderay/helpers/plugin.rb, line 114
114: def default id = nil
115: if id
116: id = validate_id id
117: raise "The default plugin can't be named \"default\"." if id == :default
118: plugin_hash[:default] = id
119: else
120: load :default
121: end
122: end
Returns an array of all .rb files in the plugin path.
The extension .rb is not included.
# File lib/coderay/helpers/plugin.rb, line 140
140: def list
141: Dir[path_to('*')].select do |file|
142: File.basename(file)[/^(?!_)\w+\.rb$/]
143: end.map do |file|
144: File.basename(file, '.rb').to_sym
145: end
146: end
This is done automatically when plugin_path is called.
# File lib/coderay/helpers/plugin.rb, line 159
159: def load_plugin_map
160: mapfile = path_to '_map'
161: @plugin_map_loaded = true
162: if File.exist? mapfile
163: require mapfile
164: true
165: else
166: false
167: end
168: 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
# File lib/coderay/helpers/plugin.rb, line 95
95: def map hash
96: for from, to in hash
97: from = validate_id from
98: to = validate_id to
99: plugin_hash[from] = to unless plugin_hash.has_key? from
100: end
101: end
The path where the plugins can be found.
# File lib/coderay/helpers/plugin.rb, line 79
79: def plugin_path *args
80: unless args.empty?
81: @plugin_path = File.expand_path File.join(*args)
82: end
83: @plugin_path ||= ''
84: end
Every plugin must register itself for id by calling register_for, which calls this method.
See Plugin#register_for.
# File lib/coderay/helpers/plugin.rb, line 128
128: def register plugin, id
129: plugin_hash[validate_id(id)] = plugin
130: end
Return a plugin hash that automatically loads plugins.
# File lib/coderay/helpers/plugin.rb, line 173
173: def make_plugin_hash
174: @plugin_map_loaded ||= false
175: Hash.new do |h, plugin_id|
176: id = validate_id(plugin_id)
177: path = path_to id
178: begin
179: raise LoadError, "#{path} not found" unless File.exist? path
180: require path
181: rescue LoadError => boom
182: if @plugin_map_loaded
183: if h.has_key?(:default)
184: warn '%p could not load plugin %p; falling back to %p' % [self, id, h[:default]]
185: h[:default]
186: else
187: raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom]
188: end
189: else
190: load_plugin_map
191: h[plugin_id]
192: end
193: else
194: # Plugin should have registered by now
195: if h.has_key? id
196: h[id]
197: else
198: raise PluginNotFound, "No #{self.name} plugin for #{id.inspect} found in #{path}."
199: end
200: end
201: end
202: end
Returns the expected path to the plugin file for the given id.
# File lib/coderay/helpers/plugin.rb, line 205
205: def path_to plugin_id
206: File.join plugin_path, "#{plugin_id}.rb"
207: 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).
# File lib/coderay/helpers/plugin.rb, line 214
214: def validate_id id
215: if id.is_a? Symbol or id.nil?
216: id
217: elsif id.is_a? String
218: if id[/\w+/] == id
219: id.downcase.to_sym
220: else
221: raise ArgumentError, "Invalid id given: #{id}"
222: end
223: else
224: raise ArgumentError, "String or Symbol expected, but #{id.class} given."
225: end
226: end