coderay 1.1.0 → 1.1.3.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/MIT-LICENSE +22 -0
- data/bin/coderay +1 -1
- data/lib/coderay.rb +9 -9
- data/lib/coderay/encoders.rb +18 -0
- data/lib/coderay/{encoder.rb → encoders/encoder.rb} +1 -12
- data/lib/coderay/encoders/html.rb +5 -4
- data/lib/coderay/encoders/html/output.rb +0 -2
- data/lib/coderay/helpers/plugin.rb +0 -219
- data/lib/coderay/helpers/plugin_host.rb +221 -0
- data/lib/coderay/scanners.rb +27 -0
- data/lib/coderay/scanners/c.rb +1 -1
- data/lib/coderay/scanners/cpp.rb +20 -18
- data/lib/coderay/scanners/diff.rb +3 -3
- data/lib/coderay/scanners/groovy.rb +2 -2
- data/lib/coderay/scanners/haml.rb +1 -1
- data/lib/coderay/scanners/java.rb +4 -4
- data/lib/coderay/scanners/java_script.rb +2 -3
- data/lib/coderay/scanners/lua.rb +1 -1
- data/lib/coderay/scanners/python.rb +1 -1
- data/lib/coderay/scanners/ruby.rb +13 -6
- data/lib/coderay/scanners/ruby/patterns.rb +2 -2
- data/lib/coderay/scanners/ruby/string_state.rb +8 -0
- data/lib/coderay/{scanner.rb → scanners/scanner.rb} +0 -18
- data/lib/coderay/scanners/sql.rb +18 -26
- data/lib/coderay/styles.rb +15 -0
- data/lib/coderay/styles/alpha.rb +2 -1
- data/lib/coderay/{style.rb → styles/style.rb} +1 -6
- data/lib/coderay/token_kinds.rb +0 -0
- data/lib/coderay/tokens.rb +3 -0
- data/lib/coderay/version.rb +1 -1
- metadata +19 -24
- data/Rakefile +0 -37
- data/test/functional/basic.rb +0 -318
- data/test/functional/examples.rb +0 -129
- data/test/functional/for_redcloth.rb +0 -78
- data/test/functional/suite.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 38dbc03e09d4f2097b25606eb9dd76d53b8034f00d0b6f11ac08cec89fba7cb7
|
4
|
+
data.tar.gz: 91ce1794b172df488c0f53c33496b13f9c71d0a062487676ea5d2b7f6e538510
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68d7d887ef40a9e1f9c237b975e8eb8e87490ed955695377727d92c4ca101b85b0d3e5dd30ff7e6d4409c54042b7d5cd6b06286855a2f462f26f0c52d5f9e618
|
7
|
+
data.tar.gz: b94ad7656cc49215461a9806dadb15eb59ce1ce5d8c5d67e6c2147668517ce3c480fff3990f1d81faf251ded1cdb9f06ef6a03253472668ce86f1fbb40b611fc
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 2005-2012 Kornelius Kalnbach <murphy@rubychan.de> (@murphy_karasu)
|
2
|
+
|
3
|
+
http://coderay.rubychan.de/
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/bin/coderay
CHANGED
@@ -35,7 +35,7 @@ defaults:
|
|
35
35
|
|
36
36
|
common:
|
37
37
|
coderay file.rb # highlight file to terminal
|
38
|
-
coderay file.rb > file.html
|
38
|
+
coderay file.rb -page > file.html # highlight file to HTML page
|
39
39
|
coderay file.rb -div > file.html # highlight file to HTML snippet
|
40
40
|
|
41
41
|
configure output:
|
data/lib/coderay.rb
CHANGED
@@ -134,7 +134,7 @@ module CodeRay
|
|
134
134
|
File.join CODERAY_PATH, *path
|
135
135
|
end
|
136
136
|
|
137
|
-
|
137
|
+
autoload :VERSION, 'coderay/version'
|
138
138
|
|
139
139
|
# helpers
|
140
140
|
autoload :FileType, coderay_path('helpers', 'file_type')
|
@@ -145,13 +145,13 @@ module CodeRay
|
|
145
145
|
autoload :TokenKinds, coderay_path('token_kinds')
|
146
146
|
|
147
147
|
# Plugin system
|
148
|
-
autoload :PluginHost, coderay_path('helpers', '
|
148
|
+
autoload :PluginHost, coderay_path('helpers', 'plugin_host')
|
149
149
|
autoload :Plugin, coderay_path('helpers', 'plugin')
|
150
150
|
|
151
151
|
# Plugins
|
152
|
-
autoload :Scanners, coderay_path('
|
153
|
-
autoload :Encoders, coderay_path('
|
154
|
-
autoload :Styles, coderay_path('
|
152
|
+
autoload :Scanners, coderay_path('scanners')
|
153
|
+
autoload :Encoders, coderay_path('encoders')
|
154
|
+
autoload :Styles, coderay_path('styles')
|
155
155
|
|
156
156
|
# convenience access and reusable Encoder/Scanner pair
|
157
157
|
autoload :Duo, coderay_path('duo')
|
@@ -166,7 +166,7 @@ module CodeRay
|
|
166
166
|
#
|
167
167
|
# See also demo/demo_simple.
|
168
168
|
def scan code, lang, options = {}, &block
|
169
|
-
TokensProxy.new code, lang, options, block
|
169
|
+
CodeRay::TokensProxy.new code, lang, options, block
|
170
170
|
end
|
171
171
|
|
172
172
|
# Scans +filename+ (a path to a code file) with the Scanner for +lang+.
|
@@ -181,7 +181,7 @@ module CodeRay
|
|
181
181
|
# require 'coderay'
|
182
182
|
# page = CodeRay.scan_file('some_c_code.c').html
|
183
183
|
def scan_file filename, lang = :auto, options = {}, &block
|
184
|
-
lang = FileType.fetch filename, :text, true if lang == :auto
|
184
|
+
lang = CodeRay::FileType.fetch filename, :text, true if lang == :auto
|
185
185
|
code = File.read filename
|
186
186
|
scan code, lang, options, &block
|
187
187
|
end
|
@@ -258,7 +258,7 @@ module CodeRay
|
|
258
258
|
# ]
|
259
259
|
# #-> 2 out of 4 tokens have the kind :integer.
|
260
260
|
def encoder format, options = {}
|
261
|
-
Encoders[format].new options
|
261
|
+
CodeRay::Encoders[format].new options
|
262
262
|
end
|
263
263
|
|
264
264
|
# Finds the Scanner class for +lang+ and creates an instance, passing
|
@@ -266,7 +266,7 @@ module CodeRay
|
|
266
266
|
#
|
267
267
|
# See Scanner.new.
|
268
268
|
def scanner lang, options = {}, &block
|
269
|
-
Scanners[lang].new '', options, &block
|
269
|
+
CodeRay::Scanners[lang].new '', options, &block
|
270
270
|
end
|
271
271
|
|
272
272
|
# Extract the options for the scanner from the +options+ hash.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CodeRay
|
2
|
+
|
3
|
+
# This module holds the Encoder class and its subclasses.
|
4
|
+
# For example, the HTML encoder is named CodeRay::Encoders::HTML
|
5
|
+
# can be found in coderay/encoders/html.
|
6
|
+
#
|
7
|
+
# Encoders also provides methods and constants for the register
|
8
|
+
# mechanism and the [] method that returns the Encoder class
|
9
|
+
# belonging to the given format.
|
10
|
+
module Encoders
|
11
|
+
|
12
|
+
extend PluginHost
|
13
|
+
plugin_path File.dirname(__FILE__), 'encoders'
|
14
|
+
|
15
|
+
autoload :Encoder, CodeRay.coderay_path('encoders', 'encoder')
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -1,17 +1,6 @@
|
|
1
1
|
module CodeRay
|
2
|
-
|
3
|
-
# This module holds the Encoder class and its subclasses.
|
4
|
-
# For example, the HTML encoder is named CodeRay::Encoders::HTML
|
5
|
-
# can be found in coderay/encoders/html.
|
6
|
-
#
|
7
|
-
# Encoders also provides methods and constants for the register
|
8
|
-
# mechanism and the [] method that returns the Encoder class
|
9
|
-
# belonging to the given format.
|
10
2
|
module Encoders
|
11
3
|
|
12
|
-
extend PluginHost
|
13
|
-
plugin_path File.dirname(__FILE__), 'encoders'
|
14
|
-
|
15
4
|
# = Encoder
|
16
5
|
#
|
17
6
|
# The Encoder base class. Together with Scanner and
|
@@ -157,7 +146,7 @@ module CodeRay
|
|
157
146
|
end
|
158
147
|
|
159
148
|
def get_output options
|
160
|
-
options[:out] || ''
|
149
|
+
options[:out] || ''.dup
|
161
150
|
end
|
162
151
|
|
163
152
|
# Append data.to_s to the output. Returns the argument.
|
@@ -25,7 +25,8 @@ module Encoders
|
|
25
25
|
# == Options
|
26
26
|
#
|
27
27
|
# === :tab_width
|
28
|
-
# Convert \t characters to +n+ spaces (a number.)
|
28
|
+
# Convert \t characters to +n+ spaces (a number or false.)
|
29
|
+
# false will keep tab characters untouched.
|
29
30
|
#
|
30
31
|
# Default: 8
|
31
32
|
#
|
@@ -175,12 +176,12 @@ module Encoders
|
|
175
176
|
|
176
177
|
if options[:wrap] || options[:line_numbers]
|
177
178
|
@real_out = @out
|
178
|
-
@out = ''
|
179
|
+
@out = ''.dup
|
179
180
|
end
|
180
181
|
|
181
182
|
@break_lines = (options[:break_lines] == true)
|
182
183
|
|
183
|
-
@HTML_ESCAPE = HTML_ESCAPE.merge("\t" => ' ' * options[:tab_width])
|
184
|
+
@HTML_ESCAPE = HTML_ESCAPE.merge("\t" => options[:tab_width] ? ' ' * options[:tab_width] : "\t")
|
184
185
|
|
185
186
|
@opened = []
|
186
187
|
@last_opened = nil
|
@@ -313,7 +314,7 @@ module Encoders
|
|
313
314
|
end
|
314
315
|
|
315
316
|
def break_lines text, style
|
316
|
-
reopen = ''
|
317
|
+
reopen = ''.dup
|
317
318
|
@opened.each_with_index do |kind, index|
|
318
319
|
reopen << (@span_for_kinds[index > 0 ? [kind, *@opened[0...index]] : kind] || '<span>')
|
319
320
|
end
|
@@ -1,224 +1,5 @@
|
|
1
1
|
module CodeRay
|
2
2
|
|
3
|
-
# = PluginHost
|
4
|
-
#
|
5
|
-
# A simple subclass/subfolder plugin system.
|
6
|
-
#
|
7
|
-
# Example:
|
8
|
-
# class Generators
|
9
|
-
# extend PluginHost
|
10
|
-
# plugin_path 'app/generators'
|
11
|
-
# end
|
12
|
-
#
|
13
|
-
# class Generator
|
14
|
-
# extend Plugin
|
15
|
-
# PLUGIN_HOST = Generators
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# class FancyGenerator < Generator
|
19
|
-
# register_for :fancy
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# Generators[:fancy] #-> FancyGenerator
|
23
|
-
# # or
|
24
|
-
# CodeRay.require_plugin 'Generators/fancy'
|
25
|
-
# # or
|
26
|
-
# Generators::Fancy
|
27
|
-
module PluginHost
|
28
|
-
|
29
|
-
# Raised if Encoders::[] fails because:
|
30
|
-
# * a file could not be found
|
31
|
-
# * the requested Plugin is not registered
|
32
|
-
PluginNotFound = Class.new LoadError
|
33
|
-
HostNotFound = Class.new LoadError
|
34
|
-
|
35
|
-
PLUGIN_HOSTS = []
|
36
|
-
PLUGIN_HOSTS_BY_ID = {} # dummy hash
|
37
|
-
|
38
|
-
# Loads all plugins using list and load.
|
39
|
-
def load_all
|
40
|
-
for plugin in list
|
41
|
-
load plugin
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
# Returns the Plugin for +id+.
|
46
|
-
#
|
47
|
-
# Example:
|
48
|
-
# yaml_plugin = MyPluginHost[:yaml]
|
49
|
-
def [] id, *args, &blk
|
50
|
-
plugin = validate_id(id)
|
51
|
-
begin
|
52
|
-
plugin = plugin_hash.[](plugin, *args, &blk)
|
53
|
-
end while plugin.is_a? String
|
54
|
-
plugin
|
55
|
-
end
|
56
|
-
|
57
|
-
alias load []
|
58
|
-
|
59
|
-
# Tries to +load+ the missing plugin by translating +const+ to the
|
60
|
-
# underscore form (eg. LinesOfCode becomes lines_of_code).
|
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
|
68
|
-
|
69
|
-
class << self
|
70
|
-
|
71
|
-
# Adds the module/class to the PLUGIN_HOSTS list.
|
72
|
-
def extended mod
|
73
|
-
PLUGIN_HOSTS << mod
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
# The path where the plugins can be found.
|
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
|
85
|
-
|
86
|
-
# Map a plugin_id to another.
|
87
|
-
#
|
88
|
-
# Usage: Put this in a file plugin_path/_map.rb.
|
89
|
-
#
|
90
|
-
# class MyColorHost < PluginHost
|
91
|
-
# map :navy => :dark_blue,
|
92
|
-
# :maroon => :brown,
|
93
|
-
# :luna => :moon
|
94
|
-
# end
|
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
|
102
|
-
|
103
|
-
# Define the default plugin to use when no plugin is found
|
104
|
-
# for a given id, or return the default plugin.
|
105
|
-
#
|
106
|
-
# See also map.
|
107
|
-
#
|
108
|
-
# class MyColorHost < PluginHost
|
109
|
-
# map :navy => :dark_blue
|
110
|
-
# default :gray
|
111
|
-
# end
|
112
|
-
#
|
113
|
-
# MyColorHost.default # loads and returns the Gray plugin
|
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
|
123
|
-
|
124
|
-
# Every plugin must register itself for +id+ by calling register_for,
|
125
|
-
# which calls this method.
|
126
|
-
#
|
127
|
-
# See Plugin#register_for.
|
128
|
-
def register plugin, id
|
129
|
-
plugin_hash[validate_id(id)] = plugin
|
130
|
-
end
|
131
|
-
|
132
|
-
# A Hash of plugion_id => Plugin pairs.
|
133
|
-
def plugin_hash
|
134
|
-
@plugin_hash ||= (@plugin_hash = make_plugin_hash).tap { load_plugin_map }
|
135
|
-
end
|
136
|
-
|
137
|
-
# Returns an array of all .rb files in the plugin path.
|
138
|
-
#
|
139
|
-
# The extension .rb is not included.
|
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
|
147
|
-
|
148
|
-
# Returns an array of all Plugins.
|
149
|
-
#
|
150
|
-
# Note: This loads all plugins using load_all.
|
151
|
-
def all_plugins
|
152
|
-
load_all
|
153
|
-
plugin_hash.values.grep(Class)
|
154
|
-
end
|
155
|
-
|
156
|
-
# Loads the map file (see map).
|
157
|
-
#
|
158
|
-
# This is done automatically when plugin_path is called.
|
159
|
-
def load_plugin_map
|
160
|
-
mapfile = path_to '_map'
|
161
|
-
if File.exist? mapfile
|
162
|
-
require mapfile
|
163
|
-
true
|
164
|
-
else
|
165
|
-
false
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
protected
|
170
|
-
|
171
|
-
# Return a plugin hash that automatically loads plugins.
|
172
|
-
def make_plugin_hash
|
173
|
-
Hash.new do |h, plugin_id|
|
174
|
-
id = validate_id(plugin_id)
|
175
|
-
path = path_to id
|
176
|
-
begin
|
177
|
-
require path
|
178
|
-
rescue LoadError => boom
|
179
|
-
if h.has_key?(:default)
|
180
|
-
h[:default]
|
181
|
-
else
|
182
|
-
raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom]
|
183
|
-
end
|
184
|
-
else
|
185
|
-
# Plugin should have registered by now
|
186
|
-
if h.has_key? id
|
187
|
-
h[id]
|
188
|
-
else
|
189
|
-
raise PluginNotFound, "No #{self.name} plugin for #{id.inspect} found in #{path}."
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# Returns the expected path to the plugin file for the given id.
|
196
|
-
def path_to plugin_id
|
197
|
-
File.join plugin_path, "#{plugin_id}.rb"
|
198
|
-
end
|
199
|
-
|
200
|
-
# Converts +id+ to a valid plugin ID String, or returns +nil+.
|
201
|
-
#
|
202
|
-
# Raises +ArgumentError+ for all other objects, or if the
|
203
|
-
# given String includes non-alphanumeric characters (\W).
|
204
|
-
def validate_id id
|
205
|
-
case id
|
206
|
-
when Symbol
|
207
|
-
id.to_s
|
208
|
-
when String
|
209
|
-
if id[/\w+/] == id
|
210
|
-
id.downcase
|
211
|
-
else
|
212
|
-
raise ArgumentError, "Invalid id given: #{id}"
|
213
|
-
end
|
214
|
-
else
|
215
|
-
raise ArgumentError, "Symbol or String expected, but #{id.class} given."
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
end
|
220
|
-
|
221
|
-
|
222
3
|
# = Plugin
|
223
4
|
#
|
224
5
|
# Plugins have to include this module.
|
@@ -0,0 +1,221 @@
|
|
1
|
+
module CodeRay
|
2
|
+
|
3
|
+
# = PluginHost
|
4
|
+
#
|
5
|
+
# A simple subclass/subfolder plugin system.
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
# class Generators
|
9
|
+
# extend PluginHost
|
10
|
+
# plugin_path 'app/generators'
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class Generator
|
14
|
+
# extend Plugin
|
15
|
+
# PLUGIN_HOST = Generators
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# class FancyGenerator < Generator
|
19
|
+
# register_for :fancy
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# Generators[:fancy] #-> FancyGenerator
|
23
|
+
# # or
|
24
|
+
# CodeRay.require_plugin 'Generators/fancy'
|
25
|
+
# # or
|
26
|
+
# Generators::Fancy
|
27
|
+
module PluginHost
|
28
|
+
|
29
|
+
# Raised if Encoders::[] fails because:
|
30
|
+
# * a file could not be found
|
31
|
+
# * the requested Plugin is not registered
|
32
|
+
PluginNotFound = Class.new LoadError
|
33
|
+
HostNotFound = Class.new LoadError
|
34
|
+
|
35
|
+
PLUGIN_HOSTS = []
|
36
|
+
PLUGIN_HOSTS_BY_ID = {} # dummy hash
|
37
|
+
|
38
|
+
# Loads all plugins using list and load.
|
39
|
+
def load_all
|
40
|
+
for plugin in list
|
41
|
+
load plugin
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns the Plugin for +id+.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
# yaml_plugin = MyPluginHost[:yaml]
|
49
|
+
def [] id, *args, &blk
|
50
|
+
plugin = validate_id(id)
|
51
|
+
begin
|
52
|
+
plugin = plugin_hash.[](plugin, *args, &blk)
|
53
|
+
end while plugin.is_a? String
|
54
|
+
plugin
|
55
|
+
end
|
56
|
+
|
57
|
+
alias load []
|
58
|
+
|
59
|
+
# Tries to +load+ the missing plugin by translating +const+ to the
|
60
|
+
# underscore form (eg. LinesOfCode becomes lines_of_code).
|
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
|
68
|
+
|
69
|
+
class << self
|
70
|
+
|
71
|
+
# Adds the module/class to the PLUGIN_HOSTS list.
|
72
|
+
def extended mod
|
73
|
+
PLUGIN_HOSTS << mod
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
# The path where the plugins can be found.
|
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
|
85
|
+
|
86
|
+
# Map a plugin_id to another.
|
87
|
+
#
|
88
|
+
# Usage: Put this in a file plugin_path/_map.rb.
|
89
|
+
#
|
90
|
+
# class MyColorHost < PluginHost
|
91
|
+
# map :navy => :dark_blue,
|
92
|
+
# :maroon => :brown,
|
93
|
+
# :luna => :moon
|
94
|
+
# end
|
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
|
102
|
+
|
103
|
+
# Define the default plugin to use when no plugin is found
|
104
|
+
# for a given id, or return the default plugin.
|
105
|
+
#
|
106
|
+
# See also map.
|
107
|
+
#
|
108
|
+
# class MyColorHost < PluginHost
|
109
|
+
# map :navy => :dark_blue
|
110
|
+
# default :gray
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# MyColorHost.default # loads and returns the Gray plugin
|
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
|
123
|
+
|
124
|
+
# Every plugin must register itself for +id+ by calling register_for,
|
125
|
+
# which calls this method.
|
126
|
+
#
|
127
|
+
# See Plugin#register_for.
|
128
|
+
def register plugin, id
|
129
|
+
plugin_hash[validate_id(id)] = plugin
|
130
|
+
end
|
131
|
+
|
132
|
+
# A Hash of plugion_id => Plugin pairs.
|
133
|
+
def plugin_hash
|
134
|
+
@plugin_hash ||= (@plugin_hash = make_plugin_hash).tap { load_plugin_map }
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns an array of all .rb files in the plugin path.
|
138
|
+
#
|
139
|
+
# The extension .rb is not included.
|
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
|
147
|
+
|
148
|
+
# Returns an array of all Plugins.
|
149
|
+
#
|
150
|
+
# Note: This loads all plugins using load_all.
|
151
|
+
def all_plugins
|
152
|
+
load_all
|
153
|
+
plugin_hash.values.grep(Class)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Loads the map file (see map).
|
157
|
+
#
|
158
|
+
# This is done automatically when plugin_path is called.
|
159
|
+
def load_plugin_map
|
160
|
+
mapfile = path_to '_map'
|
161
|
+
if File.exist? mapfile
|
162
|
+
require mapfile
|
163
|
+
true
|
164
|
+
else
|
165
|
+
false
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
protected
|
170
|
+
|
171
|
+
# Return a plugin hash that automatically loads plugins.
|
172
|
+
def make_plugin_hash
|
173
|
+
Hash.new do |h, plugin_id|
|
174
|
+
id = validate_id(plugin_id)
|
175
|
+
path = path_to id
|
176
|
+
begin
|
177
|
+
require path
|
178
|
+
rescue LoadError => boom
|
179
|
+
if h.has_key?(:default)
|
180
|
+
h[:default]
|
181
|
+
else
|
182
|
+
raise PluginNotFound, '%p could not load plugin %p: %s' % [self, id, boom]
|
183
|
+
end
|
184
|
+
else
|
185
|
+
# Plugin should have registered by now
|
186
|
+
if h.has_key? id
|
187
|
+
h[id]
|
188
|
+
else
|
189
|
+
raise PluginNotFound, "No #{self.name} plugin for #{id.inspect} found in #{path}."
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Returns the expected path to the plugin file for the given id.
|
196
|
+
def path_to plugin_id
|
197
|
+
File.join plugin_path, "#{plugin_id}.rb"
|
198
|
+
end
|
199
|
+
|
200
|
+
# Converts +id+ to a valid plugin ID String, or returns +nil+.
|
201
|
+
#
|
202
|
+
# Raises +ArgumentError+ for all other objects, or if the
|
203
|
+
# given String includes non-alphanumeric characters (\W).
|
204
|
+
def validate_id id
|
205
|
+
case id
|
206
|
+
when Symbol
|
207
|
+
id.to_s
|
208
|
+
when String
|
209
|
+
if id[/\w+/] == id
|
210
|
+
id.downcase
|
211
|
+
else
|
212
|
+
raise ArgumentError, "Invalid id given: #{id}"
|
213
|
+
end
|
214
|
+
else
|
215
|
+
raise ArgumentError, "Symbol or String expected, but #{id.class} given."
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|