OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / tk / lib / tk / namespace.rb
1 #
2 #   tk/namespace.rb : methods to manipulate Tcl/Tk namespace
3 #                           by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
4 #
5 require 'tk'
6
7 class TkNamespace < TkObject
8   extend Tk
9
10   TkCommandNames = [
11     'namespace'.freeze, 
12   ].freeze
13
14   Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
15
16   (Tk_Namespace_ID = ["ns".freeze, "00000".taint]).instance_eval{
17     @mutex = Mutex.new
18     def mutex; @mutex; end
19     freeze
20   }
21
22   Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
23
24   TkCore::INTERP.init_ip_env{
25     Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear }
26     Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear }
27   }
28
29   def TkNamespace.id2obj(id)
30     Tk_Namespace_ID_TBL.mutex.synchronize{
31       Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
32     }
33   end
34
35   #####################################
36
37   class Ensemble < TkObject
38     def __cget_cmd
39       ['namespace', 'ensemble', 'configure', self.path]
40     end
41     private :__cget_cmd
42
43     def __config_cmd
44       ['namespace', 'ensemble', 'configure', self.path]
45     end
46     private :__config_cmd
47
48     def __configinfo_struct
49       {:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil, 
50         :default_value=>nil, :current_value=>2}
51     end
52     private :__configinfo_struct
53
54     def __boolval_optkeys
55       ['prefixes']
56     end
57     private :__boolval_optkeys
58
59     def __listval_optkeys
60       ['map', 'subcommands', 'unknown']
61     end
62     private :__listval_optkeys
63
64     def self.exist?(ensemble)
65       bool(tk_call('namespace', 'ensemble', 'exists', ensemble))
66     end
67
68     def initialize(keys = {})
69       @ensemble = @path = tk_call('namespace', 'ensemble', 'create', keys)
70     end
71
72     def cget(slot)
73       if slot == :namespace || slot == 'namespace'
74         ns = super(slot)
75         Tk_Namespace_ID_TBL.mutex.synchronize{
76           if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
77             TkNamespace::Tk_Namespace_ID_TBL[ns]
78           else
79             ns
80           end
81         }
82       else
83         super(slot)
84       end
85     end
86     def cget_strict(slot)
87       if slot == :namespace || slot == 'namespace'
88         ns = super(slot)
89         Tk_Namespace_ID_TBL.mutex.synchronize{
90           if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
91             TkNamespace::Tk_Namespace_ID_TBL[ns]
92           else
93             ns
94           end
95         }
96       else
97         super(slot)
98       end
99     end
100
101     def configinfo(slot = nil)
102       if slot
103         if slot == :namespace || slot == 'namespace'
104           val = super(slot)
105           Tk_Namespace_ID_TBL.mutex.synchronize{
106             if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
107               val = TkNamespace::Tk_Namespace_ID_TBL[val]
108             end
109           }
110         else
111           val = super(slot)
112         end
113
114         if TkComm::GET_CONFIGINFO_AS_ARRAY
115           [slot.to_s, val]
116         else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
117           {slot.to_s => val}
118         end
119
120       else
121         info = super()
122
123         if TkComm::GET_CONFIGINFO_AS_ARRAY
124           Tk_Namespace_ID_TBL.mutex.synchronize{
125             info.map!{|inf| 
126               if inf[0] == 'namespace' && 
127                   TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
128                 [inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
129               else
130                 inf
131               end
132             }
133           }
134         else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
135           val = info['namespace']
136           Tk_Namespace_ID_TBL.mutex.synchronize{
137             if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
138               info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
139             end
140           }
141         end
142
143         info
144       end
145     end
146
147     def exists?
148       bool(tk_call('namespace', 'ensemble', 'exists', @path))
149     end
150   end
151
152   #####################################
153
154   class ScopeArgs < Array
155     include Tk
156
157     # alias __tk_call             tk_call
158     # alias __tk_call_without_enc tk_call_without_enc
159     # alias __tk_call_with_enc    tk_call_with_enc
160     def tk_call(*args)
161       #super('namespace', 'eval', @namespace, *args)
162       args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
163       super('namespace', 'eval', @namespace, 
164             TkCore::INTERP._merge_tklist(*args))
165     end
166     def tk_call_without_enc(*args)
167       #super('namespace', 'eval', @namespace, *args)
168       args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
169       super('namespace', 'eval', @namespace, 
170             TkCore::INTERP._merge_tklist(*args))
171     end
172     def tk_call_with_enc(*args)
173       #super('namespace', 'eval', @namespace, *args)
174       args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
175       super('namespace', 'eval', @namespace, 
176             TkCore::INTERP._merge_tklist(*args))
177     end
178
179     def initialize(namespace, *args)
180       @namespace = namespace
181       super(args.size)
182       self.replace(args)
183     end
184   end
185
186   #####################################
187
188   class NsCode < TkObject
189     def initialize(scope, use_obj_id = false)
190       @scope = scope + ' '
191       @use_obj_id = use_obj_id
192     end
193     def path
194       @scope
195     end
196     def to_eval
197       @scope
198     end
199     def call(*args)
200       ret = TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args))
201       if @use_obj_id
202         ret = TkNamespace::Tk_NsCode_RetObjID_TBL.delete(ret.to_i)
203       end
204       ret
205     end
206   end
207
208   #####################################
209
210   def install_cmd(cmd)
211     lst = tk_split_simplelist(super(cmd), false, false)
212     if lst[1] =~ /^::/
213       lst[1] = @fullname
214     else
215       lst.insert(1, @fullname)
216     end
217     TkCore::INTERP._merge_tklist(*lst)
218   end
219
220   alias __tk_call             tk_call
221   alias __tk_call_without_enc tk_call_without_enc
222   alias __tk_call_with_enc    tk_call_with_enc
223   def tk_call(*args)
224     #super('namespace', 'eval', @fullname, *args)
225     args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
226     super('namespace', 'eval', @fullname, 
227           TkCore::INTERP._merge_tklist(*args))
228   end
229   def tk_call_without_enc(*args)
230     #super('namespace', 'eval', @fullname, *args)
231     args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
232     super('namespace', 'eval', @fullname,  
233           TkCore::INTERP._merge_tklist(*args))
234   end
235   def tk_call_with_enc(*args)
236     #super('namespace', 'eval', @fullname, *args)
237     args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
238     super('namespace', 'eval', @fullname, 
239           TkCore::INTERP._merge_tklist(*args))
240   end
241   alias ns_tk_call             tk_call
242   alias ns_tk_call_without_enc tk_call_without_enc
243   alias ns_tk_call_with_enc    tk_call_with_enc
244
245   def initialize(name = nil, parent = nil)
246     unless name
247       Tk_Namespace_ID.mutex.synchronize{
248         # name = Tk_Namespace_ID.join('')
249         name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
250         Tk_Namespace_ID[1].succ!
251       }
252     end
253     name = __tk_call('namespace', 'current') if name == ''
254     if parent
255       if parent =~ /^::/
256         if name =~ /^::/
257           @fullname = parent + name
258         else
259           @fullname = parent +'::'+ name
260         end
261       else
262         ancestor = __tk_call('namespace', 'current')
263         ancestor = '' if ancestor == '::'
264         if name =~ /^::/
265           @fullname = ancestor + '::' + parent + name
266         else
267           @fullname = ancestor + '::'+ parent +'::'+ name
268         end
269       end
270     else # parent == nil
271       ancestor = __tk_call('namespace', 'current')
272       ancestor = '' if ancestor == '::'
273       if name =~ /^::/
274         @fullname = name
275       else
276         @fullname = ancestor + '::' + name
277       end
278     end
279     @path = @fullname
280     @parent = __tk_call('namespace', 'qualifiers', @fullname)
281     @name = __tk_call('namespace', 'tail', @fullname)
282
283     # create namespace
284     __tk_call('namespace', 'eval', @fullname, '')
285
286     Tk_Namespace_ID_TBL.mutex.synchronize{
287       Tk_Namespace_ID_TBL[@fullname] = self
288     }
289   end
290
291   def self.children(*args)
292     # args ::= [<namespace>] [<pattern>]
293     # <pattern> must be glob-style pattern
294     tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
295       # ns is fullname
296       Tk_Namespace_ID_TBL.mutex.synchronize{
297         if Tk_Namespace_ID_TBL.key?(ns)
298           Tk_Namespace_ID_TBL[ns]
299         else
300           ns
301         end
302       }
303     }
304   end
305   def children(pattern=None)
306     TkNamespace.children(@fullname, pattern)
307   end
308
309   def self.code(script = Proc.new)
310     TkNamespace.new('').code(script)
311   end
312 =begin
313   def code(script = Proc.new)
314     if script.kind_of?(String)
315       cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(script)}
316     elsif script.kind_of?(Proc)
317       cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(&script)}
318     else
319       fail ArgumentError, "String or Proc is expected"
320     end
321     TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code', 
322                                                 _get_eval_string(cmd, false)))
323   end
324 =end
325   def code(script = Proc.new)
326     if script.kind_of?(String)
327       cmd = proc{|*args|
328         if TkCore::WITH_RUBY_VM  ### Ruby 1.9 !!!!
329           obj = ScopeArgs.new(@fullname,*args)
330           ret = obj.instance_exec(obj, script)
331         else
332           ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
333         end
334         id = ret.object_id
335         TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
336         id
337       }
338     elsif script.kind_of?(Proc)
339       cmd = proc{|*args|
340         if TkCore::WITH_RUBY_VM  ### Ruby 1.9 !!!!
341           obj = ScopeArgs.new(@fullname,*args)
342           ret = obj.instance_exec(obj, &script)
343         else
344           ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
345         end
346         id = ret.object_id
347         TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
348         id
349       }
350     else
351       fail ArgumentError, "String or Proc is expected"
352     end
353     TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code', 
354                                                 _get_eval_string(cmd, false)), 
355                             true)
356   end
357
358   def self.current_path
359     tk_call('namespace', 'current')
360   end
361   def current_path
362     @fullname
363   end
364
365   def self.current
366     ns = self.current_path
367     Tk_Namespace_ID_TBL.mutex.synchronize{
368       if Tk_Namespace_ID_TBL.key?(ns)
369         Tk_Namespace_ID_TBL[ns]
370       else
371         ns
372       end
373     }
374   end
375   def current_namespace
376     # ns_tk_call('namespace', 'current')
377     # @fullname
378     self
379   end
380   alias current current_namespace
381
382   def self.delete(*ns_list)
383     tk_call('namespace', 'delete', *ns_list)
384     ns_list.each{|ns|
385       Tk_Namespace_ID_TBL.mutex.synchronize{
386         if ns.kind_of?(TkNamespace)
387           Tk_Namespace_ID_TBL.delete(ns.path)
388         else
389           Tk_Namespace_ID_TBL.delete(ns.to_s)
390         end
391       }
392     }
393   end
394   def delete
395     TkNamespece.delete(@fullname)
396   end
397
398   def self.ensemble_create(*keys)
399     tk_call('namespace', 'ensemble', 'create', *hash_kv(keys))
400   end
401   def self.ensemble_configure(cmd, slot, value=None)
402     if slot.kind_of?(Hash)
403       tk_call('namespace', 'ensemble', 'configure', cmd, *hash_kv(slot))
404     else
405       tk_call('namespace', 'ensemble', 'configure', cmd, '-'+slot.to_s, value)
406     end
407   end
408   def self.ensemble_configinfo(cmd, slot = nil)
409     if slot
410       tk_call('namespace', 'ensemble', 'configure', cmd, '-' + slot.to_s)
411     else
412       inf = {}
413       Hash(*tk_split_simplelist(tk_call('namespace', 'ensemble', 'configure', cmd))).each{|k, v| inf[k[1..-1]] = v}
414       inf
415     end
416   end
417   def self.ensemble_exist?(cmd)
418     bool(tk_call('namespace', 'ensemble', 'exists', cmd))
419   end
420
421   def self.eval(namespace, cmd = Proc.new, *args)
422     #tk_call('namespace', 'eval', namespace, cmd, *args)
423     TkNamespace.new(namespace).eval(cmd, *args)
424   end
425 =begin
426   def eval(cmd = Proc.new, *args)
427     #TkNamespace.eval(@fullname, cmd, *args)
428     #ns_tk_call(cmd, *args)
429     code_obj = code(cmd)
430     ret = code_obj.call(*args)
431     # uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
432     uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
433     tk_tcl2ruby(ret)
434   end
435 =end
436   def eval(cmd = Proc.new, *args)
437     code_obj = code(cmd)
438     ret = code_obj.call(*args)
439     uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
440     ret
441   end
442
443   def self.exist?(ns)
444     bool(tk_call('namespace', 'exists', ns))
445   end
446   def exist?
447     TkNamespece.exist?(@fullname)
448   end
449
450   def self.export(*patterns)
451     tk_call('namespace', 'export', *patterns)
452   end
453   def self.export_with_clear(*patterns)
454     tk_call('namespace', 'export', '-clear', *patterns)
455   end
456   def export
457     TkNamespace.export(@fullname)
458   end
459   def export_with_clear
460     TkNamespace.export_with_clear(@fullname)
461   end
462
463   def self.forget(*patterns)
464     tk_call('namespace', 'forget', *patterns)
465   end
466   def forget
467     TkNamespace.forget(@fullname)
468   end
469
470   def self.import(*patterns)
471     tk_call('namespace', 'import', *patterns)
472   end
473   def self.force_import(*patterns)
474     tk_call('namespace', 'import', '-force', *patterns)
475   end
476   def import
477     TkNamespace.import(@fullname)
478   end
479   def force_import
480     TkNamespace.force_import(@fullname)
481   end
482
483   def self.inscope(namespace, script, *args)
484     tk_call('namespace', 'inscope', namespace, script, *args)
485   end
486   def inscope(script, *args)
487     TkNamespace.inscope(@fullname, script, *args)
488   end
489
490   def self.origin(cmd)
491     tk_call('namespace', 'origin', cmd)
492   end
493
494   def self.parent(namespace=None)
495     ns = tk_call('namespace', 'parent', namespace)
496     Tk_Namespace_ID_TBL.mutex.synchronize{
497       if Tk_Namespace_ID_TBL.key?(ns)
498         Tk_Namespace_ID_TBL[ns]
499       else
500         ns
501       end
502     }
503   end
504   def parent
505     tk_call('namespace', 'parent', @fullname)
506   end
507
508   def self.get_path
509     tk_call('namespace', 'path')
510   end
511   def self.set_path(*namespace_list)
512     tk_call('namespace', 'path', array2tk_list(namespace_list))
513   end
514   def set_path
515     tk_call('namespace', 'path', @fullname)
516   end
517
518   def self.qualifiers(str)
519     tk_call('namespace', 'qualifiers', str)
520   end
521
522   def self.tail(str)
523     tk_call('namespace', 'tail', str)
524   end
525
526   def self.upvar(namespace, *var_pairs)
527     tk_call('namespace', 'upvar', namespace, *(var_pairs.flatten))
528   end
529   def upvar(*var_pairs)
530     TkNamespace.inscope(@fullname, *(var_pairs.flatten))
531   end
532
533   def self.get_unknown_handler
534     tk_tcl2ruby(tk_call('namespace', 'unknown'))
535   end
536   def self.set_unknown_handler(cmd = Proc.new)
537     tk_call('namespace', 'unknown', cmd)
538   end
539
540   def self.which(name)
541     tk_call('namespace', 'which', name)
542   end
543   def self.which_command(name)
544     tk_call('namespace', 'which', '-command', name)
545   end
546   def self.which_variable(name)
547     tk_call('namespace', 'which', '-variable', name)
548   end
549 end
550
551 TkNamespace::Global = TkNamespace.new('::')