File: tk/namespace.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  class: TkNamespace#7
extends
  Tk   
inherits from
  TkObject   
has properties
constant: TkCommandNames #10
constant: Tk_Namespace_ID_TBL #14
constant: Tk_Namespace_ID #16
method: mutex #18
constant: Tk_NsCode_RetObjID_TBL #22
class method: id2obj / 1 #29
method: install_cmd / 1 #210
alias: __tk_call tk_call #220
alias: __tk_call_without_enc tk_call_without_enc #221
alias: __tk_call_with_enc tk_call_with_enc #222
method: tk_call / 1 #223
method: tk_call_without_enc / 1 #229
method: tk_call_with_enc / 1 #235
alias: ns_tk_call tk_call #241
alias: ns_tk_call_without_enc tk_call_without_enc #242
alias: ns_tk_call_with_enc tk_call_with_enc #243
method: initialize / 2 #245
class method: children (1/2) / 1 #291
method: children (2/E) / 1 #305
class method: code (1/2) / 1 #309
method: code (2/E) / 1 #325
class method: current_path (1/2) #358
method: current_path (2/E) #361
class method: current (1/2) #365
method: current_namespace #375
alias: current (2/E) current_namespace #380
class method: delete (1/2) / 1 #382
method: delete (2/E) #394
class method: ensemble_create / 1 #398
class method: ensemble_configure / 3 #401
class method: ensemble_configinfo / 2 #408
class method: ensemble_exist? / 1 #417
class method: eval (1/2) / 3 #421
method: eval (2/E) / 2 #436
class method: exist? (1/2) / 1 #443
method: exist? (2/E) #446
class method: export (1/2) / 1 #450
class method: export_with_clear (1/2) / 1 #453
method: export (2/E) #456
method: export_with_clear (2/E) #459
class method: forget (1/2) / 1 #463
method: forget (2/E) #466
class method: import (1/2) / 1 #470
class method: force_import (1/2) / 1 #473
method: import (2/E) #476
method: force_import (2/E) #479
class method: inscope (1/2) / 3 #483
method: inscope (2/E) / 2 #486
class method: origin / 1 #490
class method: parent (1/2) / 1 #494
method: parent (2/E) #504
class method: get_path #508
class method: set_path (1/2) / 1 #511
method: set_path (2/E) #514
class method: qualifiers / 1 #518
class method: tail / 1 #522
class method: upvar (1/2) / 2 #526
method: upvar (2/E) / 1 #529
class method: get_unknown_handler #533
class method: set_unknown_handler / 1 #536
class method: which / 1 #540
class method: which_command / 1 #543
class method: which_variable / 1 #546
  class: Ensemble#37
inherits from
  TkObject   
has properties
method: __cget_cmd #38
method: __config_cmd #43
method: __configinfo_struct #48
method: __boolval_optkeys #54
method: __listval_optkeys #59
class method: exist? / 1 #64
method: initialize / 1 #68
method: cget / 1 #72
method: cget_strict / 1 #86
method: configinfo / 1 #101
method: exists? #147
  class: ScopeArgs#154
includes
  Tk   
inherits from
  Array ( Builtin-Module )
has properties
method: tk_call / 1 #160
method: tk_call_without_enc / 1 #166
method: tk_call_with_enc / 1 #172
method: initialize / 2 #179
  class: NsCode#188
inherits from
  TkObject   
has properties
method: initialize / 2 #189
method: path #193
method: to_eval #196
method: call / 1 #199

Class Hierarchy

Object ( Builtin-Module )
Array ( Builtin-Module )
  ScopeArgs ( TkNamespace ) #154
TkKernel
TkObject
  TkNamespace    #7
  Ensemble ( TkNamespace ) #37
  NsCode ( TkNamespace ) #188

Code

   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('::')