rdoba 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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