arcadia 0.1.3 → 0.2.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 +69 -77
- data/arcadia.rb +1097 -770
- data/base/a-commons.rb +480 -0
- data/base/a-contracts.rb +207 -322
- data/base/{a-utils.rb → a-tkcommons.rb} +933 -993
- data/conf/arcadia.conf +130 -203
- data/conf/arcadia.res.rb +1332 -1325
- data/ext/ae-action-dispatcher/ae-action-dispatcher.conf +6 -0
- data/ext/ae-action-dispatcher/ae-action-dispatcher.rb +22 -0
- data/ext/ae-complete-code/ae-complete-code.conf +2 -2
- data/ext/ae-complete-code/ae-complete-code.rb +82 -80
- data/ext/ae-doc-code/ae-doc-code.conf +2 -2
- data/ext/ae-doc-code/ae-doc-code.rb +114 -111
- data/ext/ae-editor/ae-editor.conf +110 -105
- data/ext/ae-editor/ae-editor.rb +2501 -2287
- data/ext/ae-editor/langs/conf.lang +15 -0
- data/ext/ae-editor/langs/lang.lang.bind +1 -0
- data/ext/ae-editor/langs/rb.lang +67 -0
- data/ext/ae-editor/langs/rbw.lang.bind +1 -0
- data/ext/ae-event-log/ae-event-log.rb +45 -52
- data/ext/ae-file-history/ae-file-history.conf +4 -4
- data/ext/ae-file-history/ae-file-history.rb +298 -286
- data/ext/ae-flag/ae-flag.conf +6 -6
- data/ext/ae-flag/ae-flag.rb +12 -12
- data/ext/ae-inspector/ae-inspector.conf +3 -3
- data/ext/ae-inspector/ae-inspector.rb +2 -2
- data/ext/ae-output-event/ae-output-event.conf +15 -15
- data/ext/ae-output/ae-output.conf +5 -3
- data/ext/ae-output/ae-output.rb +62 -33
- data/ext/ae-palette/ae-palette.conf +3 -3
- data/ext/ae-palette/ae-palette.rb +265 -306
- data/ext/ae-rad/ae-rad-inspector.rb +1534 -0
- data/{base/a-libs.rb → ext/ae-rad/ae-rad-libs.rb} +1118 -846
- data/ext/ae-rad/ae-rad-palette.rb +273 -0
- data/ext/ae-rad/ae-rad.conf +71 -0
- data/ext/ae-rad/ae-rad.rb +56 -0
- data/{lib → ext/ae-rad/lib}/tk/al-tk.rb +21 -110
- data/{lib → ext/ae-rad/lib}/tk/al-tk.res.rb +0 -0
- data/{lib → ext/ae-rad/lib}/tk/al-tkarcadia.rb +26 -26
- data/{lib → ext/ae-rad/lib}/tk/al-tkcustom.rb +70 -70
- data/{lib → ext/ae-rad/lib}/tkext/al-bwidget.rb +194 -194
- data/{lib → ext/ae-rad/lib}/tkext/al-iwidgets.rb +25 -25
- data/{lib → ext/ae-rad/lib}/tkext/al-tile.rb +173 -173
- data/{lib → ext/ae-rad/lib}/tkext/al-tktable.rb +0 -0
- data/ext/ae-ruby-debug/ae-ruby-debug.conf +7 -4
- data/ext/ae-ruby-debug/ae-ruby-debug.rb +278 -142
- data/ext/ae-search-in-files/ae-search-in-files.conf +15 -0
- data/ext/ae-search-in-files/ae-search-in-files.rb +284 -0
- data/ext/ae-shell/ae-shell.rb +88 -8
- data/ext/ae-shell/sh.rb +7 -0
- metadata +93 -79
- data/base/a-contracts-work.rb +0 -219
- data/base/a-ext.rb +0 -280
- data/ext/ae-debug/ae-debug.conf +0 -7
- data/ext/ae-debug/ae-debug.rb +0 -601
- data/ext/ae-debug/debug1.57.rb +0 -998
data/base/a-commons.rb
ADDED
@@ -0,0 +1,480 @@
|
|
1
|
+
#
|
2
|
+
# a-commons.rb - Arcadia Ruby ide
|
3
|
+
# by Antonio Galeone <antonio-galeone@rubyforge.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require "observer"
|
7
|
+
require 'singleton'
|
8
|
+
|
9
|
+
# +------------------------------------------+
|
10
|
+
# Extension
|
11
|
+
# +------------------------------------------+
|
12
|
+
|
13
|
+
class ArcadiaExt
|
14
|
+
attr_reader :arcadia
|
15
|
+
|
16
|
+
def initialize(_arcadia, _name=nil)
|
17
|
+
@arcadia = _arcadia
|
18
|
+
Arcadia.add_listener(self, BuildEvent)
|
19
|
+
Arcadia.add_listener(self, ExitQueryEvent)
|
20
|
+
Arcadia.add_listener(self, FinalizeEvent)
|
21
|
+
@name = _name
|
22
|
+
@frames = Array.new
|
23
|
+
@frames_points = conf_array("#{_name}.frames")
|
24
|
+
@frames_labels = conf_array("#{_name}.labels")
|
25
|
+
@float_frames = Array.new
|
26
|
+
# unless self.respond_to? :build
|
27
|
+
# raise NoMethodError, "ArcadiaExt needs to respond to `:build'"
|
28
|
+
# end
|
29
|
+
# unless self.respond_to? :before_build
|
30
|
+
# raise NoMethodError, "ArcadiaExt needs to respond to `:before_build'"
|
31
|
+
# end
|
32
|
+
# unless self.respond_to? :after_build
|
33
|
+
# raise NoMethodError, "ArcadiaExt needs to respond to `:after_build'"
|
34
|
+
# end
|
35
|
+
# if self.respond_to? :arcadia_update
|
36
|
+
# ObserverCallback.new(@arcadia.main_contract, self, :arcadia_update)
|
37
|
+
# end
|
38
|
+
ObjectSpace.define_finalizer(self, self.method(:finalize).to_proc)
|
39
|
+
end
|
40
|
+
|
41
|
+
def conf_array(_name)
|
42
|
+
res = []
|
43
|
+
value = @arcadia['conf'][_name]
|
44
|
+
res.concat(value.split(',')) if value
|
45
|
+
res
|
46
|
+
end
|
47
|
+
|
48
|
+
def frame(_n=0)
|
49
|
+
if @frames[_n] == nil && @frames_points[_n]
|
50
|
+
(@frames_labels[_n].nil?)? _label = @name : _label = @frames_labels[_n]
|
51
|
+
@frames[_n] = @arcadia.layout.register_panel(@frames_points[_n],@name, _label)
|
52
|
+
end
|
53
|
+
return @frames[_n]
|
54
|
+
end
|
55
|
+
|
56
|
+
def frame_free(_n=0)
|
57
|
+
if _n.nil?
|
58
|
+
@frames.each_index{|i|
|
59
|
+
@arcadia.layout.unregister_panel(@frames_points[i],@name)
|
60
|
+
@frames[i]=nil
|
61
|
+
}
|
62
|
+
else
|
63
|
+
@arcadia.layout.unregister_panel(@frames_points[_n],@name)
|
64
|
+
@frames[_n] = nil
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def frame_raise(_n=0)
|
70
|
+
if _n.nil?
|
71
|
+
@frames.each_index{|i|
|
72
|
+
@arcadia.layout.raise_panel(@frames_points[i],@name)
|
73
|
+
}
|
74
|
+
else
|
75
|
+
@arcadia.layout.raise_panel(@frames_points[_n],@name)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def frame_title(_title=nil, _n=0)
|
81
|
+
self.frames(_n) if @frames[_n] == nil
|
82
|
+
@arcadia.layout.domain(@frames_points[_n])['root'].top_text(_title)
|
83
|
+
end
|
84
|
+
|
85
|
+
def float_frame(_n=0, _args=nil)
|
86
|
+
if @float_frames[_n].nil?
|
87
|
+
@float_frames[_n] = @arcadia.layout.new_float_frame(_args)
|
88
|
+
end
|
89
|
+
@float_frames[_n]
|
90
|
+
end
|
91
|
+
|
92
|
+
def conf(_property)
|
93
|
+
@arcadia['conf'][@name+'.'+_property]
|
94
|
+
end
|
95
|
+
|
96
|
+
# def arcadia_update(_sender, _event)
|
97
|
+
#must be implemented to activate
|
98
|
+
# end
|
99
|
+
|
100
|
+
def can_exit_query
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
|
104
|
+
def finalize
|
105
|
+
#may be extendeded in child
|
106
|
+
end
|
107
|
+
|
108
|
+
def verbose
|
109
|
+
'??????'
|
110
|
+
end
|
111
|
+
|
112
|
+
def exec(_method, _args=nil)
|
113
|
+
if self.respond_to(_method)
|
114
|
+
self.send(_method, _args)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
class ObserverCallback
|
122
|
+
def initialize(_publisher, _subscriber, _method_update_to_call=:update)
|
123
|
+
@publisher = _publisher
|
124
|
+
@subscriber = _subscriber
|
125
|
+
@method=_method_update_to_call
|
126
|
+
@publisher.add_observer(self)
|
127
|
+
end
|
128
|
+
def update(*args)
|
129
|
+
@subscriber.send(@method,*args)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# +------------------------------------------+
|
134
|
+
# Event
|
135
|
+
# +------------------------------------------+
|
136
|
+
|
137
|
+
class Event
|
138
|
+
class Result
|
139
|
+
attr_reader :sender
|
140
|
+
attr_reader :time
|
141
|
+
def initialize(_sender, _args=nil)
|
142
|
+
@sender = _sender
|
143
|
+
if _args
|
144
|
+
_args.each do |key, value|
|
145
|
+
self.send(key+'=', value)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
@time = Time.new
|
149
|
+
end
|
150
|
+
end
|
151
|
+
attr_reader :sender
|
152
|
+
attr_accessor :parent
|
153
|
+
attr_reader :channel
|
154
|
+
attr_reader :time
|
155
|
+
attr_reader :results
|
156
|
+
def initialize(_sender, _args=nil)
|
157
|
+
@breaked = false
|
158
|
+
@sender = _sender
|
159
|
+
@channel = '0'
|
160
|
+
if _args
|
161
|
+
_args.each do |key, value|
|
162
|
+
#self.send(key, value)
|
163
|
+
self.send(key+'=', value)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
@time = Time.new
|
167
|
+
@results = Array.new
|
168
|
+
end
|
169
|
+
|
170
|
+
def add_result(_sender, _args=nil)
|
171
|
+
if self.class::Result
|
172
|
+
res = self.class::Result.new(_sender, _args)
|
173
|
+
else
|
174
|
+
res = Result.new(_sender, _args)
|
175
|
+
end
|
176
|
+
@results << res
|
177
|
+
res
|
178
|
+
end
|
179
|
+
|
180
|
+
def is_breaked?
|
181
|
+
@breaked
|
182
|
+
end
|
183
|
+
|
184
|
+
def break
|
185
|
+
@breaked = true
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
module EventBus #(or SourceEvent)
|
190
|
+
def process_event(_event)
|
191
|
+
return _event if !defined?(@@listeners)
|
192
|
+
event_classes = _event_class_stack(_event.class)
|
193
|
+
#before fase
|
194
|
+
event_classes.each do |_c|
|
195
|
+
_process_fase(_c, _event, 'before')
|
196
|
+
break if _event.is_breaked?
|
197
|
+
end unless _event.is_breaked?
|
198
|
+
# fase
|
199
|
+
event_classes.each do |_c|
|
200
|
+
_process_fase(_c, _event)
|
201
|
+
break if _event.is_breaked?
|
202
|
+
end unless _event.is_breaked?
|
203
|
+
#after fase
|
204
|
+
event_classes.each do |_c|
|
205
|
+
_process_fase(_c, _event, 'after')
|
206
|
+
break if _event.is_breaked?
|
207
|
+
end unless _event.is_breaked?
|
208
|
+
_event
|
209
|
+
end
|
210
|
+
|
211
|
+
def broadcast_event(_event)
|
212
|
+
return _event if !defined?(@@listeners)
|
213
|
+
event_classes = _event_class_stack(_event.class)
|
214
|
+
event_classes.each do |_c|
|
215
|
+
_broadcast_fase(_c, _event)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def _event_class_stack(_class)
|
220
|
+
#p "------> chiamato _event_class_stack for class #{_class}"
|
221
|
+
res = Array.new
|
222
|
+
cur_class = _class
|
223
|
+
while cur_class != Object
|
224
|
+
#p "#{cur_class} son on #{cur_class.superclass}"
|
225
|
+
res << cur_class
|
226
|
+
cur_class = cur_class.superclass
|
227
|
+
end
|
228
|
+
return res
|
229
|
+
end
|
230
|
+
private :_event_class_stack
|
231
|
+
|
232
|
+
def _process_fase(_class, _event, _fase_name = nil)
|
233
|
+
# _fase_name cicle
|
234
|
+
return if @@listeners[_class].nil?
|
235
|
+
_fase_name.nil?? suf = '':suf = _fase_name
|
236
|
+
#method_name = 'on_'+suf+_class.to_s.downcase.gsub('event','')
|
237
|
+
method_name = _method_name(_class, suf)
|
238
|
+
#p _method_name(_event, suf)+' == '+method_name
|
239
|
+
#p method_name
|
240
|
+
if _class != _event.class
|
241
|
+
#sub_method_name = 'on_'+suf+_event.class.to_s.downcase.gsub('event','')
|
242
|
+
sub_method_name = _method_name(_event.class, suf)
|
243
|
+
@@listeners[_class].each do|_listener|
|
244
|
+
if _listener.respond_to?(sub_method_name)
|
245
|
+
_listener.send(sub_method_name, _event)
|
246
|
+
elsif _listener.respond_to?(method_name)
|
247
|
+
_listener.send(method_name, _event)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
else
|
251
|
+
@@listeners[_class].each do|_listener|
|
252
|
+
_listener.send(method_name, _event) if _listener.respond_to?(method_name)
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
private :_process_fase
|
257
|
+
def _method_name(_class, _suf='')
|
258
|
+
_str = _class.to_s
|
259
|
+
_pre = _str[0..1]
|
260
|
+
_in = _str[2..-1]
|
261
|
+
_suf = _suf+'_' if _suf.length >0
|
262
|
+
return 'on_'+(_suf+_pre+_in.gsub(/[A-Z]/){|s| '_'+s.to_s}).downcase.gsub('_event','')
|
263
|
+
end
|
264
|
+
private :_method_name
|
265
|
+
def _broadcast_fase(_class, _event)
|
266
|
+
return if @@listeners[_class].nil?
|
267
|
+
method_name = _method_name(_class)
|
268
|
+
if _class != _event.class
|
269
|
+
sub_method_name = _method_name(_event.class)
|
270
|
+
@@listeners[_class].each do|_listener|
|
271
|
+
#p "--- method_name=>#{method_name}"
|
272
|
+
#p "--- sub_method_name=>#{sub_method_name}"
|
273
|
+
#p "--- for listener #{_listener}"
|
274
|
+
if _listener.respond_to?(sub_method_name)
|
275
|
+
Thread.new{_listener.send(sub_method_name, _event)}
|
276
|
+
elsif _listener.respond_to?(method_name)
|
277
|
+
Thread.new{_listener.send(method_name, _event)}
|
278
|
+
end
|
279
|
+
end
|
280
|
+
else
|
281
|
+
@@listeners[_class].each do|_listener|
|
282
|
+
_listener.send(method_name, _event) if _listener.respond_to?(method_name)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
private :_broadcast_fase
|
287
|
+
|
288
|
+
|
289
|
+
def add_listener(_listener, _class_event)
|
290
|
+
@@listeners = {} unless defined? @@listeners
|
291
|
+
@@listeners[_class_event] = [] unless @@listeners.has_key?(_class_event)
|
292
|
+
@@listeners[_class_event] << _listener
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
module Autils
|
299
|
+
def full_in_path_command(_command=nil)
|
300
|
+
return nil if _command.nil?
|
301
|
+
_ret = nil
|
302
|
+
RUBY_PLATFORM.include?('win32') ? _sep = ';':_sep=':'
|
303
|
+
ENV['PATH'].split(_sep).each{|_path|
|
304
|
+
_file = File.join(_path, _command)
|
305
|
+
if FileTest.exist?(_file)
|
306
|
+
_ret = _file
|
307
|
+
end
|
308
|
+
}
|
309
|
+
_ret
|
310
|
+
end
|
311
|
+
|
312
|
+
def is_windows?
|
313
|
+
!(RUBY_PLATFORM =~ /(win|w)32$/).nil?
|
314
|
+
#RUBY_PLATFORM.include?('win')
|
315
|
+
end
|
316
|
+
|
317
|
+
end
|
318
|
+
|
319
|
+
module Configurable
|
320
|
+
def properties_file2hash(_property_file)
|
321
|
+
r_hash = Hash.new
|
322
|
+
if _property_file && FileTest::exist?(_property_file)
|
323
|
+
f = File::open(_property_file,'r')
|
324
|
+
begin
|
325
|
+
_lines = f.readlines
|
326
|
+
_lines.each{|_line|
|
327
|
+
_strip_line = _line.strip
|
328
|
+
if (_strip_line.length > 0)&&(_strip_line[0,1]!='#')
|
329
|
+
var_plat = _line.split('::')
|
330
|
+
if var_plat.length > 1
|
331
|
+
if (RUBY_PLATFORM.include?(var_plat[0]))
|
332
|
+
_line = var_plat[1]
|
333
|
+
var_plat[2..-1].collect{|x| _line=_line+'::'+x} if var_plat.length > 2
|
334
|
+
else
|
335
|
+
_line = ''
|
336
|
+
end
|
337
|
+
end
|
338
|
+
var = _line.split('=')
|
339
|
+
if var.length > 1
|
340
|
+
_value = var[1].strip
|
341
|
+
var[2..-1].collect{|x| _value=_value+'='+x} if var.length > 2
|
342
|
+
r_hash[var[0].strip]=_value
|
343
|
+
end
|
344
|
+
end
|
345
|
+
}
|
346
|
+
ensure
|
347
|
+
f.close unless f.nil?
|
348
|
+
end
|
349
|
+
return r_hash
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
module Persistable
|
355
|
+
def write_persist(_persist_file)
|
356
|
+
if FileTest::exist?(_persist_file)
|
357
|
+
f = File.new(_persist_file, "w")
|
358
|
+
begin
|
359
|
+
if f
|
360
|
+
p = self['pers']
|
361
|
+
if p
|
362
|
+
p.each{|key,value|
|
363
|
+
f.syswrite(key+'='+value+"\n")
|
364
|
+
}
|
365
|
+
end
|
366
|
+
end
|
367
|
+
ensure
|
368
|
+
f.close unless f.nil?
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
class Application
|
375
|
+
extend EventBus
|
376
|
+
include Configurable
|
377
|
+
include Persistable
|
378
|
+
ApplicationParams = Struct.new( "ApplicationParams",
|
379
|
+
:name,
|
380
|
+
:version,
|
381
|
+
:config_file,
|
382
|
+
:persistent_file
|
383
|
+
)
|
384
|
+
|
385
|
+
def initialize(_ap=ApplicationParams.new)
|
386
|
+
@@instance = self
|
387
|
+
eval('$'+_ap.name+'=self')
|
388
|
+
publish('applicationParams', _ap)
|
389
|
+
publish(_ap.name,self)
|
390
|
+
@first_run = false
|
391
|
+
self['applicationParams'].persistent_file = File.join(local_dir, self['applicationParams'].name+'.pers')
|
392
|
+
if !File.exists?(self['applicationParams'].persistent_file)
|
393
|
+
File.new(self['applicationParams'].persistent_file, File::CREAT).close
|
394
|
+
end
|
395
|
+
publish('conf', properties_file2hash(self['applicationParams'].config_file)) if self['applicationParams'].config_file
|
396
|
+
publish('pers', properties_file2hash(self['applicationParams'].persistent_file)) if self['applicationParams'].persistent_file
|
397
|
+
yield(self) if block_given?
|
398
|
+
end
|
399
|
+
|
400
|
+
def Application.instance
|
401
|
+
@@instance
|
402
|
+
end
|
403
|
+
|
404
|
+
def prepare
|
405
|
+
end
|
406
|
+
|
407
|
+
def publish(_name, _obj)
|
408
|
+
@objs = Hash.new if !defined?(@objs)
|
409
|
+
if @objs[_name] == nil
|
410
|
+
@objs[_name] = _obj
|
411
|
+
else
|
412
|
+
raise("The name #{_name} already exist")
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
# this method load config file from local directory for personalizations
|
417
|
+
def load_local_config(_create_if_not_exist=true)
|
418
|
+
local_file_config = File.join(local_dir,File.basename(self['applicationParams'].config_file))
|
419
|
+
if FileTest.exist?(local_file_config)
|
420
|
+
self['conf'].update(self.properties_file2hash(local_file_config))
|
421
|
+
elsif _create_if_not_exist
|
422
|
+
if FileTest.writable?(local_dir)
|
423
|
+
f = File.new(local_file_config, "w")
|
424
|
+
begin
|
425
|
+
if f
|
426
|
+
p = self['conf']
|
427
|
+
if p
|
428
|
+
p.keys.sort.each{|key|
|
429
|
+
f.syswrite('#'+key+'='+self['conf'][key]+"\n")
|
430
|
+
}
|
431
|
+
end
|
432
|
+
end
|
433
|
+
ensure
|
434
|
+
f.close unless f.nil?
|
435
|
+
end
|
436
|
+
else
|
437
|
+
msg = "Locad dir "+'"'+local_dir+'"'+" must be writable!"
|
438
|
+
Arcadia.ok(self, 'title' => '(Arcadia)', 'msg' => msg, 'level'=>'error')
|
439
|
+
exit
|
440
|
+
|
441
|
+
end
|
442
|
+
end
|
443
|
+
end
|
444
|
+
|
445
|
+
def local_dir
|
446
|
+
_local_dir = File.join(ENV["HOME"],'.'+self['applicationParams'].name) if ENV["HOME"]
|
447
|
+
if _local_dir && !File.exist?(_local_dir)
|
448
|
+
if FileTest.exist?(ENV["HOME"])
|
449
|
+
Dir.mkdir(_local_dir)
|
450
|
+
@first_run = true
|
451
|
+
else
|
452
|
+
msg = "Locad dir "+'"'+ENV["HOME"]+'"'+" must be writable!"
|
453
|
+
Arcadia.ok(self, 'title' => "(#{self['applicationParams'].name})", 'msg' => msg, 'level'=>'error')
|
454
|
+
exit
|
455
|
+
end
|
456
|
+
end
|
457
|
+
return _local_dir
|
458
|
+
end
|
459
|
+
|
460
|
+
def create(_name, _class)
|
461
|
+
register(_name,_class.new)
|
462
|
+
end
|
463
|
+
|
464
|
+
def objects(_name)
|
465
|
+
return @objs[_name]
|
466
|
+
end
|
467
|
+
|
468
|
+
def [](_name)
|
469
|
+
if @objs[_name]
|
470
|
+
return @objs[_name]
|
471
|
+
else
|
472
|
+
raise RuntimeError, "resurce '"+_name+"' unavabled ", caller
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
def run
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
|