riel 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README +0 -0
  2. data/lib/riel/ansicolor.rb +93 -0
  3. data/lib/riel/array.rb +20 -0
  4. data/lib/riel/command.rb +30 -0
  5. data/lib/riel/date.rb +16 -0
  6. data/lib/riel/dir.rb +90 -0
  7. data/lib/riel/enumerable.rb +66 -0
  8. data/lib/riel/env.rb +49 -0
  9. data/lib/riel/file.rb +212 -0
  10. data/lib/riel/filetype.rb +189 -0
  11. data/lib/riel/hash.rb +12 -0
  12. data/lib/riel/io.rb +20 -0
  13. data/lib/riel/log.rb +548 -0
  14. data/lib/riel/matchdata.rb +13 -0
  15. data/lib/riel/optproc.rb +369 -0
  16. data/lib/riel/pathname.rb +16 -0
  17. data/lib/riel/rcfile.rb +35 -0
  18. data/lib/riel/regexp.rb +152 -0
  19. data/lib/riel/setdiff.rb +53 -0
  20. data/lib/riel/size_converter.rb +62 -0
  21. data/lib/riel/string.rb +81 -0
  22. data/lib/riel/tempfile.rb +28 -0
  23. data/lib/riel/text.rb +408 -0
  24. data/lib/riel/timer.rb +52 -0
  25. data/lib/riel.rb +13 -0
  26. data/test/riel/array_test.rb +22 -0
  27. data/test/riel/command_test.rb +28 -0
  28. data/test/riel/date_test.rb +17 -0
  29. data/test/riel/dir_test.rb +98 -0
  30. data/test/riel/enumerable_test.rb +27 -0
  31. data/test/riel/env_test.rb +52 -0
  32. data/test/riel/file_test.rb +242 -0
  33. data/test/riel/filetype_test.rb +32 -0
  34. data/test/riel/hash_test.rb +12 -0
  35. data/test/riel/io_test.rb +22 -0
  36. data/test/riel/log_test.rb +184 -0
  37. data/test/riel/matchdata_test.rb +15 -0
  38. data/test/riel/optproc_test.rb +233 -0
  39. data/test/riel/pathname_test.rb +36 -0
  40. data/test/riel/rcfile_test.rb +44 -0
  41. data/test/riel/regexp_test.rb +24 -0
  42. data/test/riel/setdiff_test.rb +26 -0
  43. data/test/riel/size_converter_test.rb +64 -0
  44. data/test/riel/string_test.rb +58 -0
  45. data/test/riel/tempfile_test.rb +16 -0
  46. data/test/riel/text_test.rb +102 -0
  47. data/test/riel/timer_test.rb +43 -0
  48. 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
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ class MatchData
5
+
6
+ origw = $-w
7
+ $-w = false
8
+ def inspect
9
+ to_a.inspect
10
+ end
11
+ $-w = origw
12
+
13
+ end