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.
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