coderay 1.1.0 → 1.1.3.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|