col 1.0.0 → 1.0.1a

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.
Files changed (5) hide show
  1. data/README +35 -35
  2. data/lib/col.rb +350 -342
  3. data/test/col.rb +241 -229
  4. data/test/col_db.rb +14 -14
  5. metadata +33 -57
data/lib/col.rb CHANGED
@@ -1,342 +1,350 @@
1
- require 'rubygems'
2
- require 'term/ansicolor'
3
-
4
- # --------------------------------------------------------------------------- #
5
-
6
- class Col
7
- # args: array of strings (to_s is called on each)
8
- def initialize(*args)
9
- @strings = args.map { |a| a.to_s }
10
- end
11
-
12
- def Col.[](*args)
13
- Col.new(*args)
14
- end
15
-
16
- COLORED_REGEXP = /\e\[ # opening character sequence
17
- (?: [34][0-7] | [0-9] ) ? # optional code
18
- ( ; (?: [34][0-7] | [0-9] ))* # more optional codes
19
- m # closing character
20
- /x
21
-
22
- # Convenience method to remove color codes from a string.
23
- # Also available as Col.plain.
24
- def Col.uncolored(string)
25
- string.gsub(COLORED_REGEXP, '')
26
- end
27
-
28
- # Convenience method to remove color codes from a string.
29
- # Also available as Col.uncolored.
30
- def Col.plain(string)
31
- string.gsub(COLORED_REGEXP, '')
32
- end
33
-
34
- def Col.inline(*args)
35
- unless args.size.even?
36
- raise Col::Error, "Col.inline requires an even number of arguments"
37
- end
38
- String.new.tap { |result|
39
- args.each_slice(2) do |string, format|
40
- result << Col(string.to_s).fmt(format)
41
- end
42
- }
43
- end
44
-
45
- # e.g.
46
- # Col("one", "two", "three", "four").fmt "rb,y,cb,_b"
47
- # # same as:
48
- # "one".red.bold + "two".yellow + "three".cyan.bold + "four".bold
49
- #
50
- # Col
51
- def fmt(*spec)
52
- ::Col::Formatter.new(@strings, *spec).result
53
- end
54
-
55
- def to_s
56
- @strings.join
57
- end
58
-
59
- def method_missing(message, *args, &block)
60
- unless args.empty?
61
- super # We're not interested in a message with arguments; NoMethodError
62
- end
63
- if Col::DB.method?(message)
64
- Col.new( self.fmt(message) ) # Col["..."].yellow -> Col
65
- # to allow Col["..."].yellow.bold
66
- else
67
- self.fmt(message) # Col["..."].gbow -> String
68
- end
69
- end
70
- end
71
-
72
- def Col(*args)
73
- Col.new(*args)
74
- end
75
-
76
- # --------------------------------------------------------------------------- #
77
-
78
- class Col::Error < StandardError
79
- end
80
-
81
- # --------------------------------------------------------------------------- #
82
-
83
- class Col::Formatter
84
- def initialize(strings, *spec)
85
- check_correct_number_of_arguments(strings, *spec)
86
- @strings = strings
87
- @format_spec = normalise_format_spec(*spec)
88
- end
89
-
90
- def result
91
- unless @strings.size == @format_spec.size
92
- raise Col::Error, "mismatching strings and specs"
93
- end
94
- String.new.tap { |str|
95
- @strings.zip(@format_spec).each do |string, spec|
96
- d = decorated_string(string, spec)
97
- str << d
98
- end
99
- }
100
- end
101
-
102
- # e.g.
103
- # string = "hello"
104
- # spec = [:yellow, :bold, :on_red]
105
- # result = "hello".send(:yellow).send(:bold).send(:on_red)
106
- def decorated_string(string, spec)
107
- raise Col::Error unless string.is_a? String and spec.is_a? Array \
108
- and spec.all? { |e| e.is_a? Symbol }
109
- spec.inject(string) { |str, symbol| Term::ANSIColor.send(symbol, str) }
110
- end
111
-
112
- #
113
- # In general, there should be the same number of arguments as there are
114
- # strings:
115
- #
116
- # Col["one"].fmt( :b )
117
- # Col["one", "two"].fmt( [:red, :on_white], [:bold, :negative] )
118
- # Col["one", "two", "three"].fmt( :yellow, [:green, :bold], :italic )
119
- # Col["one", "two", "three", "four"].fmt(:rb, :y, :cb, :m)
120
- # Col["one", "two", "three", "four"].fmt "rb,y,cb,m"
121
- #
122
- # As a special case, if there is only one string, it can have any number of
123
- # arguments:
124
- #
125
- # Col["string"].fmt( :yellow, :bold, :italic, :blink, :negative, :on_magenta )
126
- #
127
- # If the number of arguments is incorrect, a Col::Error is thrown.
128
- #
129
- def check_correct_number_of_arguments(strings, *spec)
130
- nargs = spec.size
131
- if nargs == 1 and spec.first.is_a? String
132
- nargs = spec.first.split(/,/).size
133
- end
134
- if strings.size > 1 and nargs != strings.size
135
- raise Col::Error, "incorrect number of arguments: #{render(spec)}"
136
- end
137
- end
138
-
139
- #
140
- # Each spec in the following groups is equivalent. The last one is
141
- # normalised.
142
- #
143
- # [ :rb ]
144
- # [ "rb" ]
145
- # [ [:red, :bold] ]
146
- #
147
- # [ :rb, :_n, :y ]
148
- # [ "rb", "_n", "y" ]
149
- # [ [:red, :bold], [:negative], [:yellow] ]
150
- #
151
- # [ [:green, :concealed], :blue, :bold ]
152
- # [ [:green, :concealed], [:blue], [:bold] ]
153
- #
154
- # [ "rb,y,_i,g_ow" ]
155
- # [ "rb", "y", "_i", "g_ow" ]
156
- # [ [:red, :bold], [:yellow], [:italic], [:green, :on_white] ]
157
- #
158
- # {spec} is definitely an array because it was gathered like this:
159
- # def fmt(*spec)
160
- #
161
- # "Normalised" means an array with one element for each string.
162
- # Each element is itself an array of all the properties that apply to that
163
- # string.
164
- #
165
- def normalise_format_spec(*spec)
166
- if spec.size == 1 and spec.first.is_a? String and spec.first.index(',')
167
- # ^^^ "rb,y,_n"
168
- spec = spec.first.split(',') # ['rb', 'y', '_n']
169
- normalise_format_spec(*spec)
170
- else
171
- # We have an array of items. We need to treat each item individually and
172
- # put the items together. We remove nil elements.
173
- spec.map { |item| normalise_item(item) }.compact
174
- end
175
- end
176
-
177
- # Examples
178
- # Item Normalised item
179
- # :r [:red]
180
- # "r" [:red]
181
- # :red [:red]
182
- # [:red] [:red]
183
- # "rb" [:red, :bold]
184
- # :rb [:red, :bold]
185
- # [:red, :bold] [:red, :bold]
186
- # :b [:blue]
187
- # :_b [:bold]
188
- # :__b error
189
- # :__ob [:on_blue]
190
- # "gsow" [:green, :strikethrough, :on_white]
191
- # "_noB" [:negative, :on_black]
192
- # :_ []
193
- # [:_] []
194
- # [:_, :_] []
195
- # (etc.)
196
- def normalise_item(item)
197
- case item
198
- when Symbol then normalise_string(item.to_s)
199
- when Array then normalise_array(item)
200
- when String then normalise_string(item)
201
- else raise Col::Error, "Invalid item type: #{item.class}"
202
- end
203
- end
204
-
205
- # Input: array of symbols
206
- # Result: array of symbols, each of which is a legitimate ANSIColor method
207
- # Note: underscores and nil items are removed from the array
208
- def normalise_array(array)
209
- array.reject! { |x| x.nil? or x == :_ or x == '_' }
210
- invalid_items = array.select { |item| not Col::DB.method? item }
211
- case invalid_items.size
212
- when 0 then return array
213
- when 1 then raise Col::Error, "Invalid item: #{invalid_items.first.inspect}"
214
- else raise Col::Error, "Invalid items: #{invalid_items.inspect}"
215
- end
216
- end
217
-
218
- # Examples
219
- # Input Output
220
- # r [:red]
221
- # b [:blue]
222
- # rb [:red, :bold]
223
- # red [:red]
224
- # bold [:bold]
225
- # gsow [:green, :strikethrough, :on_white]
226
- # _b [:bold]
227
- # __ob [:on_blue]
228
- # _ []
229
- def normalise_string(string)
230
- # Is it already one of the methods? If so, easy. If not, split and parse.
231
- if string == "_"
232
- []
233
- elsif Col::DB.method? string
234
- [ string.intern ]
235
- elsif (1..4).include? string.size # say: "g", "gb", "gbow"
236
- color, style, backg = extract(string)
237
- color = Col::DB.color(color) # 'g' -> :green
238
- style = Col::DB.style(style) # 'b' -> :bold
239
- backg = Col::DB.background(backg) # 'ow' -> :on_white
240
- [ color, style, backg ].compact # remove nil elements
241
- else
242
- raise Col::Error, "Invalid item: #{string.inspect}"
243
- end
244
- rescue Col::Error => e
245
- raise Col::Error, "Invalid item: #{string.inspect} (#{e.message})"
246
- end
247
-
248
- # Extracts color, style and background color.
249
- # "gbow" -> ["g", "b", "ow"]
250
- # "g" -> ["g", nil, nil]
251
- # "_b" -> [nil, "b", nil]
252
- def extract(string)
253
- string += " "
254
- color, style, backg = /^(.)(.)(..)/.match(string).captures
255
- color = nil if [' ', '_'].include? color
256
- style = nil if [' ', '_'].include? style
257
- backg = nil if [' ', '__'].include? backg
258
- [color, style, backg]
259
- end
260
-
261
- def render(spec)
262
- ( (spec.size == 1) ? spec.first : spec ).inspect
263
- end
264
- end
265
-
266
- # --------------------------------------------------------------------------- #
267
-
268
- class Col::DB
269
- COLORS = {
270
- 'B' => :black,
271
- 'r' => :red,
272
- 'g' => :green,
273
- 'y' => :yellow,
274
- 'b' => :blue,
275
- 'm' => :magenta,
276
- 'c' => :cyan,
277
- 'w' => :white
278
- }
279
-
280
- STYLES = {
281
- 'b' => :bold,
282
- 'd' => :dark,
283
- 'i' => :italic,
284
- 'u' => :underline,
285
- 'U' => :underscore,
286
- 'k' => :blink,
287
- 'r' => :rapid_blink,
288
- 'n' => :negative,
289
- 'c' => :concealed,
290
- 's' => :strikethrough,
291
- }
292
-
293
- BACKGROUND = {
294
- 'oB' => :on_black,
295
- 'or' => :on_red,
296
- 'og' => :on_green,
297
- 'oy' => :on_yellow,
298
- 'ob' => :on_blue,
299
- 'om' => :on_magenta,
300
- 'oc' => :on_cyan,
301
- 'ow' => :on_white
302
- }
303
-
304
- ALL_METHODS_SYMBOL = COLORS.values + STYLES.values + BACKGROUND.values
305
- ALL_METHODS_STRING = ALL_METHODS_SYMBOL.map { |x| x.to_s }
306
- require 'set'
307
- ALL_METHODS = Set[*ALL_METHODS_SYMBOL] + Set[*ALL_METHODS_STRING]
308
-
309
- def self.method?(x)
310
- ALL_METHODS.include? x
311
- end
312
-
313
- def self.color(key)
314
- get_value COLORS, key, "color"
315
- end
316
-
317
- def self.style(key)
318
- get_value STYLES, key, "style"
319
- end
320
-
321
- def self.background(key)
322
- get_value BACKGROUND, key, "background color"
323
- end
324
-
325
- # If the 'key' is nil, we return nil. Otherwise, we insist that the key be a
326
- # valid color, style or background color. If it's not, we raise an error
327
- # (that's what 'name' is for).
328
- #
329
- # Return the method name sought: :green, :bold, :on_white, etc.
330
- def self.get_value(hash, key, name)
331
- if key.nil?
332
- nil
333
- else
334
- method = hash[key.to_s]
335
- if method.nil?
336
- raise Col::Error, "Invalid #{name} code: #{key}"
337
- end
338
- method
339
- end
340
- end
341
-
342
- end # Col::DB
1
+ require 'rubygems'
2
+ require 'term/ansicolor'
3
+
4
+ # --------------------------------------------------------------------------- #
5
+
6
+ class Col
7
+
8
+ VERSION = "1.0.1a"
9
+
10
+ # args: array of strings (to_s is called on each)
11
+ def initialize(*args)
12
+ @strings = args.map { |a| a.to_s }
13
+ end
14
+
15
+ def Col.[](*args)
16
+ Col.new(*args)
17
+ end
18
+
19
+ COLORED_REGEXP = /\e\[ # opening character sequence
20
+ (?: [34][0-7] | [0-9] ) ? # optional code
21
+ ( ; (?: [34][0-7] | [0-9] ))* # more optional codes
22
+ m # closing character
23
+ /x
24
+
25
+ # Convenience method to remove color codes from a string.
26
+ # Also available as Col.plain.
27
+ def Col.uncolored(string)
28
+ string.gsub(COLORED_REGEXP, '')
29
+ end
30
+
31
+ # Convenience method to remove color codes from a string.
32
+ # Also available as Col.uncolored.
33
+ def Col.plain(string)
34
+ string.gsub(COLORED_REGEXP, '')
35
+ end
36
+
37
+ def Col.inline(*args)
38
+ unless args.size.even?
39
+ raise Col::Error, "Col.inline requires an even number of arguments"
40
+ end
41
+ String.new.tap { |result|
42
+ args.each_slice(2) do |string, format|
43
+ result << Col(string.to_s).fmt(format)
44
+ end
45
+ }
46
+ end
47
+
48
+ # e.g.
49
+ # Col("one", "two", "three", "four").fmt "rb,y,cb,_b"
50
+ # # same as:
51
+ # "one".red.bold + "two".yellow + "three".cyan.bold + "four".bold
52
+ #
53
+ # Col
54
+ def fmt(*spec)
55
+ ::Col::Formatter.new(@strings, *spec).result
56
+ end
57
+
58
+ def to_s
59
+ @strings.join
60
+ end
61
+
62
+ # Works nicely with puts. E.g. puts Col("...").red.bold
63
+ def to_str
64
+ to_s
65
+ end
66
+
67
+ def method_missing(message, *args, &block)
68
+ unless args.empty?
69
+ super # We're not interested in a message with arguments; NoMethodError
70
+ end
71
+ if Col::DB.method?(message)
72
+ Col.new( self.fmt(message) ) # Col["..."].yellow -> Col
73
+ # to allow Col["..."].yellow.bold
74
+ else
75
+ self.fmt(message) # Col["..."].gbow -> String
76
+ end
77
+ end
78
+ end
79
+
80
+ def Col(*args)
81
+ Col.new(*args)
82
+ end
83
+
84
+ # --------------------------------------------------------------------------- #
85
+
86
+ class Col::Error < StandardError
87
+ end
88
+
89
+ # --------------------------------------------------------------------------- #
90
+
91
+ class Col::Formatter
92
+ def initialize(strings, *spec)
93
+ check_correct_number_of_arguments(strings, *spec)
94
+ @strings = strings
95
+ @format_spec = normalise_format_spec(*spec)
96
+ end
97
+
98
+ def result
99
+ unless @strings.size == @format_spec.size
100
+ raise Col::Error, "mismatching strings and specs"
101
+ end
102
+ String.new.tap { |str|
103
+ @strings.zip(@format_spec).each do |string, spec|
104
+ d = decorated_string(string, spec)
105
+ str << d
106
+ end
107
+ }
108
+ end
109
+
110
+ # e.g.
111
+ # string = "hello"
112
+ # spec = [:yellow, :bold, :on_red]
113
+ # result = "hello".send(:yellow).send(:bold).send(:on_red)
114
+ def decorated_string(string, spec)
115
+ raise Col::Error unless string.is_a? String and spec.is_a? Array \
116
+ and spec.all? { |e| e.is_a? Symbol }
117
+ spec.inject(string) { |str, symbol| Term::ANSIColor.send(symbol, str) }
118
+ end
119
+
120
+ #
121
+ # In general, there should be the same number of arguments as there are
122
+ # strings:
123
+ #
124
+ # Col["one"].fmt( :b )
125
+ # Col["one", "two"].fmt( [:red, :on_white], [:bold, :negative] )
126
+ # Col["one", "two", "three"].fmt( :yellow, [:green, :bold], :italic )
127
+ # Col["one", "two", "three", "four"].fmt(:rb, :y, :cb, :m)
128
+ # Col["one", "two", "three", "four"].fmt "rb,y,cb,m"
129
+ #
130
+ # As a special case, if there is only one string, it can have any number of
131
+ # arguments:
132
+ #
133
+ # Col["string"].fmt( :yellow, :bold, :italic, :blink, :negative, :on_magenta )
134
+ #
135
+ # If the number of arguments is incorrect, a Col::Error is thrown.
136
+ #
137
+ def check_correct_number_of_arguments(strings, *spec)
138
+ nargs = spec.size
139
+ if nargs == 1 and spec.first.is_a? String
140
+ nargs = spec.first.split(/,/).size
141
+ end
142
+ if strings.size > 1 and nargs != strings.size
143
+ raise Col::Error, "incorrect number of arguments: #{render(spec)}"
144
+ end
145
+ end
146
+
147
+ #
148
+ # Each spec in the following groups is equivalent. The last one is
149
+ # normalised.
150
+ #
151
+ # [ :rb ]
152
+ # [ "rb" ]
153
+ # [ [:red, :bold] ]
154
+ #
155
+ # [ :rb, :_n, :y ]
156
+ # [ "rb", "_n", "y" ]
157
+ # [ [:red, :bold], [:negative], [:yellow] ]
158
+ #
159
+ # [ [:green, :concealed], :blue, :bold ]
160
+ # [ [:green, :concealed], [:blue], [:bold] ]
161
+ #
162
+ # [ "rb,y,_i,g_ow" ]
163
+ # [ "rb", "y", "_i", "g_ow" ]
164
+ # [ [:red, :bold], [:yellow], [:italic], [:green, :on_white] ]
165
+ #
166
+ # {spec} is definitely an array because it was gathered like this:
167
+ # def fmt(*spec)
168
+ #
169
+ # "Normalised" means an array with one element for each string.
170
+ # Each element is itself an array of all the properties that apply to that
171
+ # string.
172
+ #
173
+ def normalise_format_spec(*spec)
174
+ if spec.size == 1 and spec.first.is_a? String and spec.first.index(',')
175
+ # ^^^ "rb,y,_n"
176
+ spec = spec.first.split(',') # ['rb', 'y', '_n']
177
+ normalise_format_spec(*spec)
178
+ else
179
+ # We have an array of items. We need to treat each item individually and
180
+ # put the items together. We remove nil elements.
181
+ spec.map { |item| normalise_item(item) }.compact
182
+ end
183
+ end
184
+
185
+ # Examples
186
+ # Item Normalised item
187
+ # :r [:red]
188
+ # "r" [:red]
189
+ # :red [:red]
190
+ # [:red] [:red]
191
+ # "rb" [:red, :bold]
192
+ # :rb [:red, :bold]
193
+ # [:red, :bold] [:red, :bold]
194
+ # :b [:blue]
195
+ # :_b [:bold]
196
+ # :__b error
197
+ # :__ob [:on_blue]
198
+ # "gsow" [:green, :strikethrough, :on_white]
199
+ # "_noB" [:negative, :on_black]
200
+ # :_ []
201
+ # [:_] []
202
+ # [:_, :_] []
203
+ # (etc.)
204
+ def normalise_item(item)
205
+ case item
206
+ when Symbol then normalise_string(item.to_s)
207
+ when Array then normalise_array(item)
208
+ when String then normalise_string(item)
209
+ else raise Col::Error, "Invalid item type: #{item.class}"
210
+ end
211
+ end
212
+
213
+ # Input: array of symbols
214
+ # Result: array of symbols, each of which is a legitimate ANSIColor method
215
+ # Note: underscores and nil items are removed from the array
216
+ def normalise_array(array)
217
+ array.reject! { |x| x.nil? or x == :_ or x == '_' }
218
+ invalid_items = array.select { |item| not Col::DB.method? item }
219
+ case invalid_items.size
220
+ when 0 then return array
221
+ when 1 then raise Col::Error, "Invalid item: #{invalid_items.first.inspect}"
222
+ else raise Col::Error, "Invalid items: #{invalid_items.inspect}"
223
+ end
224
+ end
225
+
226
+ # Examples
227
+ # Input Output
228
+ # r [:red]
229
+ # b [:blue]
230
+ # rb [:red, :bold]
231
+ # red [:red]
232
+ # bold [:bold]
233
+ # gsow [:green, :strikethrough, :on_white]
234
+ # _b [:bold]
235
+ # __ob [:on_blue]
236
+ # _ []
237
+ def normalise_string(string)
238
+ # Is it already one of the methods? If so, easy. If not, split and parse.
239
+ if string == "_"
240
+ []
241
+ elsif Col::DB.method? string
242
+ [ string.intern ]
243
+ elsif (1..4).include? string.size # say: "g", "gb", "gbow"
244
+ color, style, backg = extract(string)
245
+ color = Col::DB.color(color) # 'g' -> :green
246
+ style = Col::DB.style(style) # 'b' -> :bold
247
+ backg = Col::DB.background(backg) # 'ow' -> :on_white
248
+ [ color, style, backg ].compact # remove nil elements
249
+ else
250
+ raise Col::Error, "Invalid item: #{string.inspect}"
251
+ end
252
+ rescue Col::Error => e
253
+ raise Col::Error, "Invalid item: #{string.inspect} (#{e.message})"
254
+ end
255
+
256
+ # Extracts color, style and background color.
257
+ # "gbow" -> ["g", "b", "ow"]
258
+ # "g" -> ["g", nil, nil]
259
+ # "_b" -> [nil, "b", nil]
260
+ def extract(string)
261
+ string += " "
262
+ color, style, backg = /^(.)(.)(..)/.match(string).captures
263
+ color = nil if [' ', '_'].include? color
264
+ style = nil if [' ', '_'].include? style
265
+ backg = nil if [' ', '__'].include? backg
266
+ [color, style, backg]
267
+ end
268
+
269
+ def render(spec)
270
+ ( (spec.size == 1) ? spec.first : spec ).inspect
271
+ end
272
+ end
273
+
274
+ # --------------------------------------------------------------------------- #
275
+
276
+ class Col::DB
277
+ COLORS = {
278
+ 'B' => :black,
279
+ 'r' => :red,
280
+ 'g' => :green,
281
+ 'y' => :yellow,
282
+ 'b' => :blue,
283
+ 'm' => :magenta,
284
+ 'c' => :cyan,
285
+ 'w' => :white
286
+ }
287
+
288
+ STYLES = {
289
+ 'b' => :bold,
290
+ 'd' => :dark,
291
+ 'i' => :italic,
292
+ 'u' => :underline,
293
+ 'U' => :underscore,
294
+ 'k' => :blink,
295
+ 'r' => :rapid_blink,
296
+ 'n' => :negative,
297
+ 'c' => :concealed,
298
+ 's' => :strikethrough,
299
+ }
300
+
301
+ BACKGROUND = {
302
+ 'oB' => :on_black,
303
+ 'or' => :on_red,
304
+ 'og' => :on_green,
305
+ 'oy' => :on_yellow,
306
+ 'ob' => :on_blue,
307
+ 'om' => :on_magenta,
308
+ 'oc' => :on_cyan,
309
+ 'ow' => :on_white
310
+ }
311
+
312
+ ALL_METHODS_SYMBOL = COLORS.values + STYLES.values + BACKGROUND.values
313
+ ALL_METHODS_STRING = ALL_METHODS_SYMBOL.map { |x| x.to_s }
314
+ require 'set'
315
+ ALL_METHODS = Set[*ALL_METHODS_SYMBOL] + Set[*ALL_METHODS_STRING]
316
+
317
+ def self.method?(x)
318
+ ALL_METHODS.include? x
319
+ end
320
+
321
+ def self.color(key)
322
+ get_value COLORS, key, "color"
323
+ end
324
+
325
+ def self.style(key)
326
+ get_value STYLES, key, "style"
327
+ end
328
+
329
+ def self.background(key)
330
+ get_value BACKGROUND, key, "background color"
331
+ end
332
+
333
+ # If the 'key' is nil, we return nil. Otherwise, we insist that the key be a
334
+ # valid color, style or background color. If it's not, we raise an error
335
+ # (that's what 'name' is for).
336
+ #
337
+ # Return the method name sought: :green, :bold, :on_white, etc.
338
+ def self.get_value(hash, key, name)
339
+ if key.nil?
340
+ nil
341
+ else
342
+ method = hash[key.to_s]
343
+ if method.nil?
344
+ raise Col::Error, "Invalid #{name} code: #{key}"
345
+ end
346
+ method
347
+ end
348
+ end
349
+
350
+ end # Col::DB