rdoba 0.9.3 → 0.9.4

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/lib/rdoba/log.rb DELETED
@@ -1,419 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # Author:: Malo Skrylevo <majioa@yandex.ru>
4
- # License:: MIT
5
- #
6
- # TODO add enum of options hash to convert values to symbols
7
- # TODO make common format, and format for each of methods >, >>, +, -, %, *
8
- # TODO add syntax redefinition ability for the methods >, >>, +, -, %, *
9
- # TODO add multiple output (to more than only the IO)
10
-
11
- module Rdoba
12
-
13
- ##
14
- # Adds a Log instance to the specified object as a variable or directly into
15
- # the object itself. It returns the rdoba logger object.
16
- #
17
- # The argument accepted are only +options+ as a Hash of keys and values.
18
- #
19
- # The options keys are accepted the following: +as+, +in+, +functions+,
20
- # +prefix+, and +io+.
21
- #
22
- # Option +functions+ defines the function list that can be used in it.
23
- # Undeclared in the list functions just do nothing. It should be provided
24
- # as an Array of function descriptions of String or Symbol class. The
25
- # function list is the following: +info+, +warn+, +basic+, +extended+,
26
- # +leave+, +enter+, +compat+. If omitted it is defaulting to +enter+, and
27
- # +leave+ functions.
28
- #
29
- # The function +info+ provides just info along the code, of course it just
30
- # can be shewn by +puts+, but it also can be disabled by settings. The call
31
- # method is :*. Example:
32
- #
33
- # class A
34
- # rdoba :log => { :functions => [ :info ] }
35
- # def a
36
- # log * "Some Info"
37
- # end
38
- # end
39
- #
40
- # The function +warn+ provide justs warn message along the code, of course
41
- # it just can be shewn by +puts+, or +p+, but it also can be disabled by
42
- # settings. The call method is :%. Example:
43
- #
44
- # class A
45
- # rdoba :log => { :functions => [ :warn ] }
46
- # def a
47
- # log % "Some Info"
48
- # end
49
- # end
50
- #
51
- # The function +basic+ provides just basic debug message, it also can be
52
- # disabled by settings. The call method is :>. Example:
53
- #
54
- # class A
55
- # rdoba :log => { :functions => [ :basic ] }
56
- # def a
57
- # v = 123434
58
- # log > { :v => v }
59
- # end
60
- # end
61
- #
62
- # The function +extended+ provides extended debug message, class inspect
63
- # dumps can be used for messages of this function, it also can be
64
- # disabled by settings. The call method is :>>. Example:
65
- #
66
- # class A
67
- # rdoba :log => { :functions => [ :extended ] }
68
- # def a
69
- # v = ObjectSpace.new
70
- # vv = Object.new
71
- # log >> { :v => v, :vv => vv }
72
- # end
73
- # end
74
- #
75
- # The function +enter+ provides just debug message on function entry, it
76
- # also can be disabled by settings. The call method is :+. Example:
77
- #
78
- # class A
79
- # rdoba :log => { :functions => [ :enter ] }
80
- # def a *args
81
- # log + { :args => args }
82
- # end
83
- # end
84
- #
85
- # The function +leave+ provides just debug message on function leave, it
86
- # also can be disabled by settings. It accepts the just a argument, also
87
- # returns the provided argument, so it can be used in chain. The call
88
- # method is :-. Example:
89
- #
90
- # class A
91
- # rdoba :log => { :functions => [ :leave ] }
92
- # def a
93
- # log - 1
94
- # end
95
- # end
96
- #
97
- # A.new.a # >> 1
98
- #
99
- # The function +compat+ provides old style log strings dbgXX just for
100
- # compatibility, and will be removed.
101
- #
102
- # Option +prefix+ defines the prefix that will be shewn before the message
103
- # text. The following prefix features are available: +timestamp+, +pid+,
104
- # +function_name+, +function_line+, +function+. The full format is the
105
- # following:
106
- #
107
- # [<timestamp>]{pid}(<function module>:<function name>.<function line>)
108
- # <log type> <text>
109
- #
110
- # Here is the function module, function name, function line represents
111
- # +function+ at whole.
112
- #
113
- # The log types are of the functions previously described, and can be:
114
- # >, >>, ***, %%%, +++, ---.
115
- #
116
- # Option +io+ defines the IO to output the debug message to. It must
117
- # contain all IO methods required. It is defaulting to $stdout. Also
118
- # StringIO object is allowed.
119
- #
120
- # class A
121
- # rdoba :log => { :io => $stderr }
122
- # def a
123
- # log - 1
124
- # end
125
- # end
126
- #
127
- # Option +as+ defines the name of a method to apply the log functions to.
128
- # It is defaulting to :log, but when you've specified :self the log functions
129
- # is being embedded into the caller class instance directly.
130
- # It should be provided as a Symbol or String. Example:
131
- #
132
- # class A
133
- # rdoba :log => { :as => :self, :functions => [ :basic ] }
134
- # def a
135
- # self > "Debug"
136
- # end
137
- # end
138
- #
139
- # Option +in+ defines the name of a target class or a namespace to log
140
- # implement to. For toplevel it is defaulting to Kernel namespace, for
141
- # in-class is defaulting to the self class. It should be provided as a
142
- # constant of the class/module. Example:
143
- #
144
- # class A
145
- # def a
146
- # self > "Debug"
147
- # end
148
- # end
149
- #
150
- # rdoba :log => { :in => A, :functions => [ :basic ] }
151
- #
152
- # To compeletly disable the debug messages for the specific class
153
- # you can use either the RDOBA_LOG environment variable:
154
- #
155
- # $ RDOBA_LOG=0
156
- #
157
- # or redeclare the function list for the specific class to empty.
158
- #
159
- # rdoba :log => { :in => MyClass, :functions => [] }
160
- #
161
- def self.log options = {}
162
- Rdoba::Log.class_variable_set :@@options, options
163
-
164
- functions = [ options[ :functions ] ].flatten
165
- funcname = ( options[ :as ] ||= :log ).to_s.to_sym
166
- target = options[ :in ] || options[ :self ]
167
-
168
- if target.class == Object
169
- Rdoba::Log.log_instance_setup( TOPLEVEL_BINDING.eval 'self' )
170
- else
171
- Rdoba::Log.log_class_setup target ; end
172
-
173
- if funcname == :self
174
- Rdoba::Log.define_methods( target,
175
- [ :+, :-, :>, :>>, :*, :%, :>=, :<= ] )
176
-
177
- Rdoba::Log.try_define_compat( functions, target )
178
- target.__rdoba_log__
179
- else
180
- if target.class == Object
181
- Rdoba::Log.log_link_for :instance, target, funcname
182
- else
183
- Rdoba::Log.log_link_for :class, target, funcname ; end ; end ; end
184
-
185
- module Log
186
- @@enabled = !( ENV[ "RDOBA_LOG" ].to_s !~ /^(true|1|)$/ )
187
-
188
- def self.enabled?
189
- @@enabled ; end
190
-
191
- class Error < StandardError
192
- def initialize options = {}
193
- case options
194
- when :compat
195
- "Debug compatibility mode can't be enabled for " +
196
- "the specified object"
197
- when :main
198
- "An :as option can't be default or set to 'self' value for " +
199
- "a main application. Please set up it correctly" ; end ; end ; end
200
-
201
- module DebugCompat # TODO compat
202
- def dbgl
203
- @dbgl; end
204
-
205
- def dbgl= level
206
- @dbgl = level; end
207
-
208
- def dbc level
209
- level = level.to_i
210
- if level > 0
211
- clevel = @dbgl || begin
212
- eval "$dbgl_#{self.class}"
213
- rescue
214
- nil; end
215
- clevel || ( clevel.to_i & level ) == level
216
- else
217
- false; end; end
218
-
219
- def dbp level, text
220
- if dbc level
221
- Kernel.puts text; end; end
222
-
223
- def dbg level, code, vars = {}
224
- if dbc level
225
- if vars
226
- vars.each_pair do |var, value|
227
- instance_variable_set( var, value ); end; end
228
- eval code; end; end; end
229
-
230
- module Functions
231
- include Rdoba::Log::DebugCompat
232
-
233
- def <= functions = []
234
- self.class <= functions; end
235
-
236
- def >= functions = []
237
- self.class >= functions; end
238
-
239
- def e *args
240
- io =
241
- case args.last
242
- when IO
243
- args.pop
244
- else
245
- $stderr ; end
246
- e = $! || args.shift
247
- dump = ( [ $@ || args.shift ] + args ).flatten.compact
248
- io.send :puts, "#{e.class}:%> #{e}\n\t#{dump.join("\n\t")}"; end
249
-
250
- def get_stack_function_data_at_level( level )
251
- raise Exception
252
- rescue Exception
253
- #TODO check match a method containing '`'
254
- $@[ level ] =~ /([^\/]+):(\d+):in `(.*?)'$/
255
- [ $1, $3, $2 ]; end; end
256
-
257
- module ClassFunctions
258
- def <= functions
259
- Rdoba::Log::update_functions functions, self, :+ ; end
260
-
261
- def >= functions
262
- Rdoba::Log::update_functions functions, self, :- ; end; end
263
-
264
- Initfunc = proc do
265
- self.class_variable_set :@@rdoba_log_prefix,
266
- Rdoba::Log.log_init_prefix( self )
267
- self.class_variable_set :@@rdoba_log_io_method,
268
- Rdoba::Log.log_init_io_m
269
- extend Rdoba::Log::ClassFunctions
270
- include Rdoba::Log::Functions
271
- self <= Rdoba::Log.class_variable_get( :@@options )[ :functions ]; end
272
-
273
- def self.log_init_prefix obj, is_self = false
274
- options = Rdoba::Log.class_variable_get :@@options
275
- pfx = ';if Rdoba::Log.enabled?;(Rdoba::Log::log @@rdoba_log_io_method,"'
276
- if prefix = ( options[ :prefix ].is_a?( Array ) && options[ :prefix ] ||
277
- [ options[ :prefix ] ] )
278
- if prefix.include?( :timestamp )
279
- pfx << '[#{Time.now.strftime( "%H:%M:%S.%N" )}]'; end
280
- if prefix.include?( :pid )
281
- pfx << '{#{Process.pid}}'; end
282
- if prefix.include?( :function )
283
- pfx << '(#{m,f,l=get_stack_function_data_at_level(2);m}:#{f}.#{l})'
284
- elsif prefix.include?( :function_name )
285
- if prefix.include?( :function_line )
286
- pfx << '(#{_,f,l=get_stack_function_data_at_level(2);f}.#{l})'
287
- else
288
- pfx << '(#{get_stack_function_data_at_level(2)[1]})'
289
- end ; end ; end
290
- pfx ; end
291
-
292
- def self.log_init_io_m options = {}
293
- options = Rdoba::Log.class_variable_get :@@options
294
- io = options[ :io ] || $stdout
295
- # TODO puts costomize
296
- io_m = io.method :puts ; end
297
-
298
- def self.log_class_setup obj
299
- obj.class_eval "class RdobaLog;end"
300
- obj.class_eval "def __rdoba_log__;@__rdoba_log__||=RdobaLog.new;end"
301
- obj.class_eval "class << self; def self.__rdoba_log__;
302
- @__rdoba_log__||=RdobaLog.new;end;end"
303
- obj.class_eval "def self.__rdoba_log__;
304
- @__rdoba_log__||=#{obj}::RdobaLog.new;end"
305
- obj::RdobaLog.class_eval &Initfunc ; end
306
-
307
- def self.log_instance_setup obj
308
- obj.instance_eval "class ::RdobaLog;end"
309
- obj.instance_eval "def __rdoba_log__;$__rdoba_log__||=::RdobaLog.new;end"
310
- obj.instance_eval "class << self; def self.__rdoba_log__;
311
- $__rdoba_log__||=::RdobaLog.new;end;end"
312
- obj.instance_eval "def self.__rdoba_log__;
313
- $__rdoba_log__||=::RdobaLog.new;end"
314
- ::RdobaLog.class_eval &Initfunc ; end
315
-
316
- def self.log_link_for target, obj, funcname
317
- obj.send( "#{target}_eval", "def #{funcname};__rdoba_log__;end" )
318
- obj.send( "#{target}_eval", "def self.#{funcname};__rdoba_log__;end" )
319
- obj.send( "#{target}_eval", "class << self; def self.#{funcname};
320
- __rdoba_log__;end;end" ) ; end
321
-
322
- def self.define_methods obj, list
323
- list.each do| f |
324
- evas = "def #{f} *args;__rdoba_log__.#{f} *args;end"
325
- if obj.class != Object
326
- obj.class_eval( evas ) ; end
327
- obj.instance_eval( evas ) ; end ; end
328
-
329
- def self.try_define_compat functions, target
330
- if functions.include?( :compat )
331
- list = [ :dbgl= ]
332
- (1..0xF).each do |x|
333
- (1..0xF).each do |y|
334
- idx = sprintf( "%x%x", x, y )
335
- list << "dbp#{idx}".to_sym << "dbg#{idx}".to_sym ; end; end
336
- Rdoba::Log.define_methods( target, list ) ; end ; end
337
-
338
- def self.log_functions_set obj, functions
339
- obj.class_variable_set :@@rdoba_log_functions, functions ; end
340
-
341
- def self.log_functions_get obj
342
- obj.class_variable_get :@@rdoba_log_functions
343
- rescue
344
- [] ; end
345
-
346
- def self.log_prefix_get obj
347
- obj.class_variable_get :@@rdoba_log_prefix
348
- rescue
349
- ';if true;(File.join "' ; end
350
-
351
- def self.update_functions functions, obj, method
352
- if functions.is_a?( Array ) && functions.include?( :* )
353
- functions = [ :basic, :enter, :leave, :warn, :info, :extended,
354
- :compat ] ; end # TODO compat
355
- cf = self.log_functions_get obj
356
- functions = cf.send( method, functions.is_a?( Array ) && functions ||
357
- functions.is_a?( NilClass) && [] ||
358
- [ functions.to_s.to_sym ] )
359
- self.log_functions_set obj, functions
360
-
361
- pfx = self.log_prefix_get obj
362
- code = Rdoba::Log::make_code functions, pfx
363
- obj.class_eval code ; end
364
-
365
- def self.make_code functions, pfx
366
- code = ''
367
- psfx = ' ",params);end;end;'
368
- if functions.include?( :enter )
369
- code << 'def + *params' + pfx + '<<<' + psfx
370
- else
371
- code << 'def + *params;end;'; end
372
- if functions.include?( :leave )
373
- code << 'def - ev' + pfx + '>>> ",[[ev.inspect]]);end;ev;end;'
374
- else
375
- code << 'def - ev;ev;end;'; end
376
- if functions.include?( :basic )
377
- code << "def > *params#{pfx}>#{psfx}"
378
- else
379
- code << 'def > *params;end;'; end
380
- if functions.include?( :extended )
381
- code << 'def >> *params' + pfx + '>>' + psfx
382
- else
383
- code << 'def >> *params;end;'; end
384
- if functions.include?( :warn )
385
- code << "def % *params#{pfx}%%%#{psfx}"
386
- else
387
- code << 'def % *params;end;'; end
388
- if functions.include?( :info )
389
- code << "def * *params#{pfx}***#{psfx}"
390
- else
391
- code << 'def * *params;end;'; end
392
- if functions.include?( :compat )
393
- code << "$dbgl_#{self.class}=0;"
394
- (1..0xF).each do |x|
395
- (1..0xF).each do |y|
396
- idx = sprintf "%x%x", x, y
397
- code << "def dbp#{idx}(text); dbp(0x#{idx},text); end;"
398
- code << "def dbg#{idx}(text); dbg(0x#{idx},text); end;"; end; end; end
399
- code; end
400
-
401
- def self.log io_m, prefix, params
402
- text = prefix
403
- text << params.map do |prm|
404
- case prm
405
- when Hash
406
- r = []
407
- prm.each do |key, value| r << "#{key}: #{value.inspect}" end
408
- r.join(", ")
409
- when Array
410
- prm.join(', ')
411
- when String
412
- prm
413
- else
414
- prm.inspect
415
- end
416
- end.join(', ')
417
- # NOTE: the shell over text id requires to proper output
418
- # in multiprocess environment
419
- io_m.call "#{text}\n"; end ; end ; end