riel 1.0.0
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.
- data/README +0 -0
- data/lib/riel/ansicolor.rb +93 -0
- data/lib/riel/array.rb +20 -0
- data/lib/riel/command.rb +30 -0
- data/lib/riel/date.rb +16 -0
- data/lib/riel/dir.rb +90 -0
- data/lib/riel/enumerable.rb +66 -0
- data/lib/riel/env.rb +49 -0
- data/lib/riel/file.rb +212 -0
- data/lib/riel/filetype.rb +189 -0
- data/lib/riel/hash.rb +12 -0
- data/lib/riel/io.rb +20 -0
- data/lib/riel/log.rb +548 -0
- data/lib/riel/matchdata.rb +13 -0
- data/lib/riel/optproc.rb +369 -0
- data/lib/riel/pathname.rb +16 -0
- data/lib/riel/rcfile.rb +35 -0
- data/lib/riel/regexp.rb +152 -0
- data/lib/riel/setdiff.rb +53 -0
- data/lib/riel/size_converter.rb +62 -0
- data/lib/riel/string.rb +81 -0
- data/lib/riel/tempfile.rb +28 -0
- data/lib/riel/text.rb +408 -0
- data/lib/riel/timer.rb +52 -0
- data/lib/riel.rb +13 -0
- data/test/riel/array_test.rb +22 -0
- data/test/riel/command_test.rb +28 -0
- data/test/riel/date_test.rb +17 -0
- data/test/riel/dir_test.rb +98 -0
- data/test/riel/enumerable_test.rb +27 -0
- data/test/riel/env_test.rb +52 -0
- data/test/riel/file_test.rb +242 -0
- data/test/riel/filetype_test.rb +32 -0
- data/test/riel/hash_test.rb +12 -0
- data/test/riel/io_test.rb +22 -0
- data/test/riel/log_test.rb +184 -0
- data/test/riel/matchdata_test.rb +15 -0
- data/test/riel/optproc_test.rb +233 -0
- data/test/riel/pathname_test.rb +36 -0
- data/test/riel/rcfile_test.rb +44 -0
- data/test/riel/regexp_test.rb +24 -0
- data/test/riel/setdiff_test.rb +26 -0
- data/test/riel/size_converter_test.rb +64 -0
- data/test/riel/string_test.rb +58 -0
- data/test/riel/tempfile_test.rb +16 -0
- data/test/riel/text_test.rb +102 -0
- data/test/riel/timer_test.rb +43 -0
- metadata +134 -0
data/lib/riel/log.rb
ADDED
@@ -0,0 +1,548 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
# -*- ruby -*-
|
3
|
+
#
|
4
|
+
# = log.rb
|
5
|
+
#
|
6
|
+
# Logging Module
|
7
|
+
#
|
8
|
+
# Author:: Jeff Pacec <jpace@incava.org>
|
9
|
+
# Documentation:: Author
|
10
|
+
#
|
11
|
+
|
12
|
+
require 'riel/ansicolor'
|
13
|
+
|
14
|
+
#
|
15
|
+
# == Log
|
16
|
+
#
|
17
|
+
# Very minimal logging output. If verbose is set, this displays the method and
|
18
|
+
# line number whence called. It can be a mixin to a class, which displays the
|
19
|
+
# class and method from where it called. If not in a class, it displays only the
|
20
|
+
# method.
|
21
|
+
#
|
22
|
+
# Remember: all kids love log.
|
23
|
+
#
|
24
|
+
# == Examples
|
25
|
+
#
|
26
|
+
# See the unit tests in log_test.rb
|
27
|
+
#
|
28
|
+
# == Usage
|
29
|
+
#
|
30
|
+
# The most general usage is simply to call:
|
31
|
+
#
|
32
|
+
# Log.log "some message"
|
33
|
+
#
|
34
|
+
# That will simply log the given message.
|
35
|
+
#
|
36
|
+
# class YourClass
|
37
|
+
# include Loggable
|
38
|
+
#
|
39
|
+
# def some_method(...)
|
40
|
+
# log "my message"
|
41
|
+
#
|
42
|
+
# That will log from the given class and method, showing the line number from
|
43
|
+
# which the logger was called.
|
44
|
+
#
|
45
|
+
# def another_method(...)
|
46
|
+
# stack "my message"
|
47
|
+
#
|
48
|
+
# That will produce a stack trace from the given location.
|
49
|
+
#
|
50
|
+
|
51
|
+
module RIEL
|
52
|
+
|
53
|
+
class Log
|
54
|
+
|
55
|
+
$LOGGING_LEVEL = nil
|
56
|
+
|
57
|
+
attr_accessor :quiet
|
58
|
+
attr_accessor :output
|
59
|
+
attr_accessor :colorize_line
|
60
|
+
attr_accessor :level
|
61
|
+
attr_accessor :ignored_files
|
62
|
+
attr_accessor :ignored_methods
|
63
|
+
attr_accessor :ignored_classes
|
64
|
+
attr_accessor :trim
|
65
|
+
|
66
|
+
#
|
67
|
+
|
68
|
+
module Severity
|
69
|
+
DEBUG = 0
|
70
|
+
INFO = 1
|
71
|
+
WARN = 2
|
72
|
+
ERROR = 3
|
73
|
+
FATAL = 4
|
74
|
+
end
|
75
|
+
|
76
|
+
include Log::Severity
|
77
|
+
|
78
|
+
FRAME_RE = Regexp.new('(.*):(\d+)(?::in \`(.*)\')?')
|
79
|
+
|
80
|
+
def initialize
|
81
|
+
set_defaults
|
82
|
+
end
|
83
|
+
|
84
|
+
def verbose=(v)
|
85
|
+
@level = case v
|
86
|
+
when TrueClass
|
87
|
+
DEBUG
|
88
|
+
when FalseClass
|
89
|
+
FATAL
|
90
|
+
when Integer
|
91
|
+
v
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def set_defaults
|
96
|
+
$LOGGING_LEVEL = @level = FATAL
|
97
|
+
@ignored_files = {}
|
98
|
+
@ignored_methods = {}
|
99
|
+
@ignored_classes = {}
|
100
|
+
@width = 0
|
101
|
+
@output = $stdout
|
102
|
+
@colors = []
|
103
|
+
@colorize_line = false
|
104
|
+
@quiet = false
|
105
|
+
@trim = true
|
106
|
+
|
107
|
+
set_default_widths
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_default_widths
|
111
|
+
set_widths(-15, 4, -20)
|
112
|
+
end
|
113
|
+
|
114
|
+
def verbose
|
115
|
+
level <= DEBUG
|
116
|
+
end
|
117
|
+
|
118
|
+
# Assigns output to a file with the given name. Returns the file; client
|
119
|
+
# is responsible for closing it.
|
120
|
+
def outfile=(f)
|
121
|
+
@output = if f.kind_of?(IO) then f else File.new(f, "w") end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Creates a printf format for the given widths, for aligning output. To lead
|
125
|
+
# lines with zeros (e.g., "00317") the line_width argument must be a string,
|
126
|
+
# not an integer.
|
127
|
+
def set_widths(file_width, line_width, func_width)
|
128
|
+
@file_width = file_width
|
129
|
+
@line_width = line_width
|
130
|
+
@function_width = func_width
|
131
|
+
|
132
|
+
@format = "[%#{file_width}s:%#{line_width}d] {%#{func_width}s}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def ignore_file(fname)
|
136
|
+
ignored_files[fname] = true
|
137
|
+
end
|
138
|
+
|
139
|
+
def ignore_method(methname)
|
140
|
+
ignored_methods[methname] = true
|
141
|
+
end
|
142
|
+
|
143
|
+
def ignore_class(classname)
|
144
|
+
ignored_classes[classname] = true
|
145
|
+
end
|
146
|
+
|
147
|
+
def log_file(fname)
|
148
|
+
ignored_files.delete(fname)
|
149
|
+
end
|
150
|
+
|
151
|
+
def log_method(methname)
|
152
|
+
ignored_methods.delete(methname)
|
153
|
+
end
|
154
|
+
|
155
|
+
def log_class(classname)
|
156
|
+
ignored_classes.delete(classname)
|
157
|
+
end
|
158
|
+
|
159
|
+
def debug(msg = "", depth = 1, &blk)
|
160
|
+
log(msg, DEBUG, depth + 1, &blk)
|
161
|
+
end
|
162
|
+
|
163
|
+
def info(msg = "", depth = 1, &blk)
|
164
|
+
log(msg, INFO, depth + 1, &blk)
|
165
|
+
end
|
166
|
+
|
167
|
+
def warn(msg = "", depth = 1, &blk)
|
168
|
+
log(msg, WARN, depth + 1, &blk)
|
169
|
+
end
|
170
|
+
|
171
|
+
def error(msg = "", depth = 1, &blk)
|
172
|
+
log(msg, ERROR, depth + 1, &blk)
|
173
|
+
end
|
174
|
+
|
175
|
+
def fatal(msg = "", depth = 1, &blk)
|
176
|
+
log(msg, FATAL, depth + 1, &blk)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Logs the given message.
|
180
|
+
def log(msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk)
|
181
|
+
if lvl >= level
|
182
|
+
frame = caller(depth)[0]
|
183
|
+
print_stack_frame(frame, cname, msg, lvl, &blk)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Shows the current stack.
|
188
|
+
def stack(msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk)
|
189
|
+
if lvl >= level
|
190
|
+
stk = caller(depth)
|
191
|
+
for frame in stk
|
192
|
+
print_stack_frame(frame, cname, msg, lvl, &blk)
|
193
|
+
msg = ""
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def print_stack_frame(frame, cname, msg, lvl, &blk)
|
199
|
+
md = FRAME_RE.match(frame)
|
200
|
+
file, line, func = md[1], md[2], (md[3] || "")
|
201
|
+
file.sub!(/.*\//, "")
|
202
|
+
|
203
|
+
if cname
|
204
|
+
func = cname + "#" + func
|
205
|
+
end
|
206
|
+
|
207
|
+
if ignored_files[file] || (cname && ignored_classes[cname]) || ignored_methods[func]
|
208
|
+
# skip this one.
|
209
|
+
else
|
210
|
+
print_formatted(file, line, func, msg, lvl, &blk)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def trim_to(str, maxlen)
|
215
|
+
str[0 ... maxlen.to_i.abs]
|
216
|
+
end
|
217
|
+
|
218
|
+
def print_formatted(file, line, func, msg, lvl, &blk)
|
219
|
+
if trim
|
220
|
+
file = trim_to(file, @file_width)
|
221
|
+
line = trim_to(line, @line_width)
|
222
|
+
func = trim_to(func, @function_width)
|
223
|
+
end
|
224
|
+
|
225
|
+
hdr = sprintf @format, file, line, func
|
226
|
+
print(hdr, msg, lvl, &blk)
|
227
|
+
end
|
228
|
+
|
229
|
+
def print(hdr, msg, lvl, &blk)
|
230
|
+
if blk
|
231
|
+
x = blk.call
|
232
|
+
if x.kind_of?(String)
|
233
|
+
msg = x
|
234
|
+
else
|
235
|
+
return
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
if @colors[lvl]
|
240
|
+
if colorize_line
|
241
|
+
@output.puts @colors[lvl] + hdr + " " + msg.to_s.chomp + ANSIColor.reset
|
242
|
+
else
|
243
|
+
@output.puts hdr + " " + @colors[lvl] + msg.to_s.chomp + ANSIColor.reset
|
244
|
+
end
|
245
|
+
else
|
246
|
+
@output.puts hdr + " " + msg.to_s.chomp
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def set_color(lvl, color)
|
251
|
+
@colors[lvl] = ANSIColor::code(color)
|
252
|
+
end
|
253
|
+
|
254
|
+
# by default, class methods delegate to a single app-wide log.
|
255
|
+
|
256
|
+
@@log = Log.new
|
257
|
+
|
258
|
+
# Returns the logger of the log. A class method delegating to an instance
|
259
|
+
# method ... not so good. But temporary.
|
260
|
+
def self.logger
|
261
|
+
@@log
|
262
|
+
end
|
263
|
+
|
264
|
+
ANSIColor::ATTRIBUTES.sort.each do |attr|
|
265
|
+
methname = attr[0]
|
266
|
+
# puts "methname: #{methname}"
|
267
|
+
instmeth = Array.new
|
268
|
+
instmeth << "def #{methname}(msg = \"\", lvl = DEBUG, depth = 1, cname = nil, &blk)"
|
269
|
+
instmeth << " log(\"\\e[#{attr[1]}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
|
270
|
+
instmeth << "end"
|
271
|
+
instance_eval instmeth.join("\n")
|
272
|
+
|
273
|
+
clsmeth = Array.new
|
274
|
+
clsmeth << "def #{methname}(msg = \"\", lvl = DEBUG, depth = 1, cname = nil, &blk)"
|
275
|
+
clsmeth << " logger.#{methname}(\"\\e[#{attr[1]}m\#{msg\}\\e[0m\", lvl, depth + 1, cname, &blk)"
|
276
|
+
clsmeth << "end"
|
277
|
+
# clsmeth << "def #{methname}(msg, *args)"
|
278
|
+
# clsmeth << " logger.#{methname}(msg, *args)"
|
279
|
+
# clsmeth << "end"
|
280
|
+
# puts "clsmeth: #{clsmeth}"
|
281
|
+
class_eval clsmeth.join("\n")
|
282
|
+
end
|
283
|
+
|
284
|
+
def self.set_default_widths
|
285
|
+
logger.set_default_widths
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.verbose
|
289
|
+
logger.verbose
|
290
|
+
end
|
291
|
+
|
292
|
+
def self.verbose=(v)
|
293
|
+
logger.verbose = v && v != 0 ? DEBUG : FATAL
|
294
|
+
end
|
295
|
+
|
296
|
+
def self.level=(lvl)
|
297
|
+
logger.level = lvl
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.quiet
|
301
|
+
logger.quiet
|
302
|
+
end
|
303
|
+
|
304
|
+
def self.quiet=(q)
|
305
|
+
logger.quiet = q
|
306
|
+
end
|
307
|
+
|
308
|
+
def self.format
|
309
|
+
logger.format
|
310
|
+
end
|
311
|
+
|
312
|
+
def self.format=(fmt)
|
313
|
+
logger.format = fmt
|
314
|
+
end
|
315
|
+
|
316
|
+
# Assigns output to the given stream.
|
317
|
+
def self.output=(io)
|
318
|
+
logger.output = io
|
319
|
+
end
|
320
|
+
|
321
|
+
def self.output
|
322
|
+
logger.output
|
323
|
+
end
|
324
|
+
|
325
|
+
# sets whether to colorize the entire line, or just the message.
|
326
|
+
def self.colorize_line=(col)
|
327
|
+
logger.colorize_line = col
|
328
|
+
end
|
329
|
+
|
330
|
+
def self.colorize_line
|
331
|
+
logger.colorize_line
|
332
|
+
end
|
333
|
+
|
334
|
+
# Assigns output to a file with the given name. Returns the file; client
|
335
|
+
# is responsible for closing it.
|
336
|
+
def self.outfile=(fname)
|
337
|
+
logger.outfile = fname
|
338
|
+
end
|
339
|
+
|
340
|
+
def self.outfile
|
341
|
+
logger.outfile
|
342
|
+
end
|
343
|
+
|
344
|
+
# Creates a printf format for the given widths, for aligning output.
|
345
|
+
def self.set_widths(file_width, line_width, func_width)
|
346
|
+
logger.set_widths(file_width, line_width, func_width)
|
347
|
+
end
|
348
|
+
|
349
|
+
def self.ignore_file(fname)
|
350
|
+
logger.ignore_file(fname)
|
351
|
+
end
|
352
|
+
|
353
|
+
def self.ignore_method(methname)
|
354
|
+
logger.ignored_method(methname)
|
355
|
+
end
|
356
|
+
|
357
|
+
def self.ignore_class(classname)
|
358
|
+
logger.ignored_class(classname)
|
359
|
+
end
|
360
|
+
|
361
|
+
def self.log_file(fname)
|
362
|
+
logger.log_file(fname)
|
363
|
+
end
|
364
|
+
|
365
|
+
def self.log_method(methname)
|
366
|
+
logger.log_method(methname)
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.log_class(classname)
|
370
|
+
logger.log_class(classname)
|
371
|
+
end
|
372
|
+
|
373
|
+
def self.debug(msg = "", depth = 1, &blk)
|
374
|
+
logger.log(msg, DEBUG, depth + 1, &blk)
|
375
|
+
end
|
376
|
+
|
377
|
+
def self.info(msg = "", depth = 1, &blk)
|
378
|
+
logger.log(msg, INFO, depth + 1, &blk)
|
379
|
+
end
|
380
|
+
|
381
|
+
def self.fatal(msg = "", depth = 1, &blk)
|
382
|
+
logger.log(msg, FATAL, depth + 1, &blk)
|
383
|
+
end
|
384
|
+
|
385
|
+
def self.log(msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk)
|
386
|
+
logger.log(msg, lvl, depth + 1, cname, &blk)
|
387
|
+
end
|
388
|
+
|
389
|
+
def self.stack(msg = "", lvl = DEBUG, depth = 1, cname = nil, &blk)
|
390
|
+
logger.stack(msg, lvl, depth + 1, cname, &blk)
|
391
|
+
end
|
392
|
+
|
393
|
+
def self.warn(msg = "", depth = 1, &blk)
|
394
|
+
if verbose
|
395
|
+
logger.log(msg, WARN, depth + 1, &blk)
|
396
|
+
else
|
397
|
+
$stderr.puts "WARNING: " + msg
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def self.error(msg = "", depth = 1, &blk)
|
402
|
+
if verbose
|
403
|
+
logger.log(msg, ERROR, depth + 1, &blk)
|
404
|
+
else
|
405
|
+
$stderr.puts "ERROR: " + msg
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def self.write(msg, depth = 1, cname = nil, &blk)
|
410
|
+
if verbose
|
411
|
+
stack(msg, Log::WARN, depth + 1, cname, &blk)
|
412
|
+
elsif quiet
|
413
|
+
# nothing
|
414
|
+
else
|
415
|
+
$stderr.puts msg
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
def self.set_color(lvl, color)
|
420
|
+
logger.set_color(lvl, color)
|
421
|
+
end
|
422
|
+
|
423
|
+
end
|
424
|
+
|
425
|
+
|
426
|
+
class AppLog < Log
|
427
|
+
include Log::Severity
|
428
|
+
|
429
|
+
end
|
430
|
+
|
431
|
+
|
432
|
+
module Loggable
|
433
|
+
|
434
|
+
# Logs the given message, including the class whence invoked.
|
435
|
+
def log(msg = "", lvl = Log::DEBUG, depth = 1, &blk)
|
436
|
+
Log.log(msg, lvl, depth + 1, self.class.to_s, &blk)
|
437
|
+
end
|
438
|
+
|
439
|
+
def debug(msg = "", depth = 1, &blk)
|
440
|
+
Log.log(msg, Log::DEBUG, depth + 1, self.class.to_s, &blk)
|
441
|
+
end
|
442
|
+
|
443
|
+
def info(msg = "", depth = 1, &blk)
|
444
|
+
Log.log(msg, Log::INFO, depth + 1, self.class.to_s, &blk)
|
445
|
+
end
|
446
|
+
|
447
|
+
def warn(msg = "", depth = 1, &blk)
|
448
|
+
Log.log(msg, Log::WARN, depth + 1, self.class.to_s, &blk)
|
449
|
+
end
|
450
|
+
|
451
|
+
def error(msg = "", depth = 1, &blk)
|
452
|
+
Log.log(msg, Log::ERROR, depth + 1, self.class.to_s, &blk)
|
453
|
+
end
|
454
|
+
|
455
|
+
def fatal(msg = "", depth = 1, &blk)
|
456
|
+
Log.log(msg, Log::FATAL, depth + 1, self.class.to_s, &blk)
|
457
|
+
end
|
458
|
+
|
459
|
+
def stack(msg = "", lvl = Log::DEBUG, depth = 1, &blk)
|
460
|
+
Log.stack(msg, lvl, depth + 1, self.class.to_s, &blk)
|
461
|
+
end
|
462
|
+
|
463
|
+
def write(msg = "", depth = 1, &blk)
|
464
|
+
Log.write(msg, depth + 1, self.class.to_s, &blk)
|
465
|
+
end
|
466
|
+
|
467
|
+
ANSIColor::ATTRIBUTES.sort.each do |attr|
|
468
|
+
methname = attr[0]
|
469
|
+
# puts "methname: #{methname}"
|
470
|
+
meth = Array.new
|
471
|
+
meth << "def #{methname}(msg = \"\", lvl = Log::DEBUG, depth = 1, &blk)"
|
472
|
+
meth << " Log.#{methname}(msg, lvl, depth + 1, self.class.to_s, &blk)"
|
473
|
+
meth << "end"
|
474
|
+
# puts "meth: #{meth}"
|
475
|
+
module_eval meth.join("\n")
|
476
|
+
end
|
477
|
+
|
478
|
+
end
|
479
|
+
|
480
|
+
end
|
481
|
+
|
482
|
+
include RIEL
|
483
|
+
|
484
|
+
|
485
|
+
if __FILE__ == $0
|
486
|
+
Log.verbose = true
|
487
|
+
Log.set_widths 15, -5, -35
|
488
|
+
#Log.outfile = "/tmp/log." + $$.to_s
|
489
|
+
|
490
|
+
class Demo
|
491
|
+
include Loggable
|
492
|
+
|
493
|
+
def initialize
|
494
|
+
# log "hello"
|
495
|
+
Log.set_color(Log::DEBUG, "cyan")
|
496
|
+
Log.set_color(Log::INFO, "bold cyan")
|
497
|
+
Log.set_color(Log::WARN, "reverse")
|
498
|
+
Log.set_color(Log::ERROR, "bold red")
|
499
|
+
Log.set_color(Log::FATAL, "bold white on red")
|
500
|
+
end
|
501
|
+
|
502
|
+
def meth
|
503
|
+
# log
|
504
|
+
|
505
|
+
i = 4
|
506
|
+
# info { "i: #{i}" }
|
507
|
+
|
508
|
+
i /= 3
|
509
|
+
debug { "i: #{i}" }
|
510
|
+
|
511
|
+
i **= 3
|
512
|
+
info "i: #{i}"
|
513
|
+
|
514
|
+
i **= 2
|
515
|
+
warn "i: #{i}"
|
516
|
+
|
517
|
+
i <<= 4
|
518
|
+
error "i: #{i}"
|
519
|
+
|
520
|
+
i <<= 1
|
521
|
+
fatal "i: #{i}"
|
522
|
+
end
|
523
|
+
|
524
|
+
end
|
525
|
+
|
526
|
+
class Another
|
527
|
+
include Loggable
|
528
|
+
|
529
|
+
def Another.cmeth
|
530
|
+
# /// "Log" only in instance methods
|
531
|
+
# log "I'm sorry, Dave, I'm afraid I can't do that."
|
532
|
+
|
533
|
+
# But this is legal.
|
534
|
+
Log.log "happy, happy, joy, joy"
|
535
|
+
end
|
536
|
+
end
|
537
|
+
|
538
|
+
demo = Demo.new
|
539
|
+
demo.meth
|
540
|
+
|
541
|
+
# Log.colorize_line = true
|
542
|
+
|
543
|
+
# demo.meth
|
544
|
+
# Another.cmeth
|
545
|
+
|
546
|
+
# Log.info "we are done."
|
547
|
+
|
548
|
+
end
|