1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/ext/tk/lib/tk/namespace.rb
nagai b72256f91c * ext/tk/lib/tkextlib/tktable/tktable.rb: fix bug on arguments for Proc object.
* ext/tk/sample/scrollframe.rb: forgot a Module definition.

* ext/tk/extconf.rb: check unsupported version of tclConfig.sh/tkConfig.sh. It is because current Ruby/Tk doesn't support Tcl/Tk8.6.

* ext/tk/extconf.rb: change search step of Tcl/Tk libraries.

* ext/tk/lib/tk/namespace.rb: instance_exec() cannot accept a script string.

* ext/tk/lib/tk/msgcat.rb: bug fix on treating encodings. Now, ext/tk/sample/tkmsgcat-load_rb*.rb will work.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43923 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2013-11-29 15:44:25 +00:00

546 lines
14 KiB
Ruby

#
# tk/namespace.rb : methods to manipulate Tcl/Tk namespace
# by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
#
require 'tk'
class TkNamespace < TkObject
extend Tk
TkCommandNames = [
'namespace'.freeze,
].freeze
Tk_Namespace_ID_TBL = TkCore::INTERP.create_table
(Tk_Namespace_ID = ["ns".freeze, TkUtil.untrust("00000")]).instance_eval{
@mutex = Mutex.new
def mutex; @mutex; end
freeze
}
Tk_NsCode_RetObjID_TBL = TkCore::INTERP.create_table
TkCore::INTERP.init_ip_env{
Tk_Namespace_ID_TBL.mutex.synchronize{ Tk_Namespace_ID_TBL.clear }
Tk_NsCode_RetObjID_TBL.mutex.synchronize{ Tk_NsCode_RetObjID_TBL.clear }
}
def TkNamespace.id2obj(id)
Tk_Namespace_ID_TBL.mutex.synchronize{
Tk_Namespace_ID_TBL[id]? Tk_Namespace_ID_TBL[id]: id
}
end
#####################################
class Ensemble < TkObject
def __cget_cmd
['namespace', 'ensemble', 'configure', self.path]
end
private :__cget_cmd
def __config_cmd
['namespace', 'ensemble', 'configure', self.path]
end
private :__config_cmd
def __configinfo_struct
{:key=>0, :alias=>nil, :db_name=>nil, :db_class=>nil,
:default_value=>nil, :current_value=>2}
end
private :__configinfo_struct
def __boolval_optkeys
['prefixes']
end
private :__boolval_optkeys
def __listval_optkeys
['map', 'subcommands', 'unknown']
end
private :__listval_optkeys
def self.exist?(ensemble)
bool(tk_call('namespace', 'ensemble', 'exists', ensemble))
end
def initialize(keys = {})
@ensemble = @path = tk_call('namespace', 'ensemble', 'create', keys)
end
def cget(slot)
if slot == :namespace || slot == 'namespace'
ns = super(slot)
Tk_Namespace_ID_TBL.mutex.synchronize{
if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
TkNamespace::Tk_Namespace_ID_TBL[ns]
else
ns
end
}
else
super(slot)
end
end
def cget_strict(slot)
if slot == :namespace || slot == 'namespace'
ns = super(slot)
Tk_Namespace_ID_TBL.mutex.synchronize{
if TkNamespace::Tk_Namespace_ID_TBL.key?(ns)
TkNamespace::Tk_Namespace_ID_TBL[ns]
else
ns
end
}
else
super(slot)
end
end
def configinfo(slot = nil)
if slot
if slot == :namespace || slot == 'namespace'
val = super(slot)
Tk_Namespace_ID_TBL.mutex.synchronize{
if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
val = TkNamespace::Tk_Namespace_ID_TBL[val]
end
}
else
val = super(slot)
end
if TkComm::GET_CONFIGINFO_AS_ARRAY
[slot.to_s, val]
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
{slot.to_s => val}
end
else
info = super()
if TkComm::GET_CONFIGINFO_AS_ARRAY
Tk_Namespace_ID_TBL.mutex.synchronize{
info.map!{|inf|
if inf[0] == 'namespace' &&
TkNamespace::Tk_Namespace_ID_TBL.key?(inf[-1])
[inf[0], TkNamespace::Tk_Namespace_ID_TBL[inf[-1]]]
else
inf
end
}
}
else # ! TkComm::GET_CONFIGINFO_AS_ARRAY
val = info['namespace']
Tk_Namespace_ID_TBL.mutex.synchronize{
if TkNamespace::Tk_Namespace_ID_TBL.key?(val)
info['namespace'] = TkNamespace::Tk_Namespace_ID_TBL[val]
end
}
end
info
end
end
def exists?
bool(tk_call('namespace', 'ensemble', 'exists', @path))
end
end
#####################################
class ScopeArgs < Array
include Tk
# alias __tk_call tk_call
# alias __tk_call_without_enc tk_call_without_enc
# alias __tk_call_with_enc tk_call_with_enc
def tk_call(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_without_enc(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_with_enc(*args)
#super('namespace', 'eval', @namespace, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @namespace,
TkCore::INTERP._merge_tklist(*args))
end
def initialize(namespace, *args)
@namespace = namespace
super(args.size)
self.replace(args)
end
end
#####################################
class NsCode < TkObject
def initialize(scope, use_obj_id = false)
@scope = scope + ' '
@use_obj_id = use_obj_id
end
def path
@scope
end
def to_eval
@scope
end
def call(*args)
ret = TkCore::INTERP._eval_without_enc(@scope + array2tk_list(args))
if @use_obj_id
ret = TkNamespace::Tk_NsCode_RetObjID_TBL.delete(ret.to_i)
end
ret
end
end
#####################################
def install_cmd(cmd)
lst = tk_split_simplelist(super(cmd), false, false)
if lst[1] =~ /^::/
lst[1] = @fullname
else
lst.insert(1, @fullname)
end
TkCore::INTERP._merge_tklist(*lst)
end
alias __tk_call tk_call
alias __tk_call_without_enc tk_call_without_enc
alias __tk_call_with_enc tk_call_with_enc
def tk_call(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_without_enc(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
def tk_call_with_enc(*args)
#super('namespace', 'eval', @fullname, *args)
args = args.collect{|arg| (s = _get_eval_string(arg, true))? s: ''}
super('namespace', 'eval', @fullname,
TkCore::INTERP._merge_tklist(*args))
end
alias ns_tk_call tk_call
alias ns_tk_call_without_enc tk_call_without_enc
alias ns_tk_call_with_enc tk_call_with_enc
def initialize(name = nil, parent = nil)
unless name
Tk_Namespace_ID.mutex.synchronize{
# name = Tk_Namespace_ID.join('')
name = Tk_Namespace_ID.join(TkCore::INTERP._ip_id_)
Tk_Namespace_ID[1].succ!
}
end
name = __tk_call('namespace', 'current') if name == ''
if parent
if parent =~ /^::/
if name =~ /^::/
@fullname = parent + name
else
@fullname = parent +'::'+ name
end
else
ancestor = __tk_call('namespace', 'current')
ancestor = '' if ancestor == '::'
if name =~ /^::/
@fullname = ancestor + '::' + parent + name
else
@fullname = ancestor + '::'+ parent +'::'+ name
end
end
else # parent == nil
ancestor = __tk_call('namespace', 'current')
ancestor = '' if ancestor == '::'
if name =~ /^::/
@fullname = name
else
@fullname = ancestor + '::' + name
end
end
@path = @fullname
@parent = __tk_call('namespace', 'qualifiers', @fullname)
@name = __tk_call('namespace', 'tail', @fullname)
# create namespace
__tk_call('namespace', 'eval', @fullname, '')
Tk_Namespace_ID_TBL.mutex.synchronize{
Tk_Namespace_ID_TBL[@fullname] = self
}
end
def self.children(*args)
# args ::= [<namespace>] [<pattern>]
# <pattern> must be glob-style pattern
tk_split_simplelist(tk_call('namespace', 'children', *args)).collect{|ns|
# ns is fullname
Tk_Namespace_ID_TBL.mutex.synchronize{
if Tk_Namespace_ID_TBL.key?(ns)
Tk_Namespace_ID_TBL[ns]
else
ns
end
}
}
end
def children(pattern=None)
TkNamespace.children(@fullname, pattern)
end
def self.code(script = Proc.new)
TkNamespace.new('').code(script)
end
=begin
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(script)}
elsif script.kind_of?(Proc)
cmd = proc{|*args| ScopeArgs.new(@fullname,*args).instance_eval(&script)}
else
fail ArgumentError, "String or Proc is expected"
end
TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
_get_eval_string(cmd, false)))
end
=end
def code(script = Proc.new)
if script.kind_of?(String)
cmd = proc{|*args|
ret = ScopeArgs.new(@fullname,*args).instance_eval(script)
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
}
elsif script.kind_of?(Proc)
cmd = proc{|*args|
if TkCore::WITH_RUBY_VM ### Ruby 1.9 !!!!
obj = ScopeArgs.new(@fullname,*args)
ret = obj.instance_exec(obj, &script)
else
ret = ScopeArgs.new(@fullname,*args).instance_eval(&script)
end
id = ret.object_id
TkNamespace::Tk_NsCode_RetObjID_TBL[id] = ret
id
}
else
fail ArgumentError, "String or Proc is expected"
end
TkNamespace::NsCode.new(tk_call_without_enc('namespace', 'code',
_get_eval_string(cmd, false)),
true)
end
def self.current_path
tk_call('namespace', 'current')
end
def current_path
@fullname
end
def self.current
ns = self.current_path
Tk_Namespace_ID_TBL.mutex.synchronize{
if Tk_Namespace_ID_TBL.key?(ns)
Tk_Namespace_ID_TBL[ns]
else
ns
end
}
end
def current_namespace
# ns_tk_call('namespace', 'current')
# @fullname
self
end
alias current current_namespace
def self.delete(*ns_list)
tk_call('namespace', 'delete', *ns_list)
ns_list.each{|ns|
Tk_Namespace_ID_TBL.mutex.synchronize{
if ns.kind_of?(TkNamespace)
Tk_Namespace_ID_TBL.delete(ns.path)
else
Tk_Namespace_ID_TBL.delete(ns.to_s)
end
}
}
end
def delete
TkNamespece.delete(@fullname)
end
def self.ensemble_create(*keys)
tk_call('namespace', 'ensemble', 'create', *hash_kv(keys))
end
def self.ensemble_configure(cmd, slot, value=None)
if slot.kind_of?(Hash)
tk_call('namespace', 'ensemble', 'configure', cmd, *hash_kv(slot))
else
tk_call('namespace', 'ensemble', 'configure', cmd, '-'+slot.to_s, value)
end
end
def self.ensemble_configinfo(cmd, slot = nil)
if slot
tk_call('namespace', 'ensemble', 'configure', cmd, '-' + slot.to_s)
else
inf = {}
Hash(*tk_split_simplelist(tk_call('namespace', 'ensemble', 'configure', cmd))).each{|k, v| inf[k[1..-1]] = v}
inf
end
end
def self.ensemble_exist?(cmd)
bool(tk_call('namespace', 'ensemble', 'exists', cmd))
end
def self.eval(namespace, cmd = Proc.new, *args)
#tk_call('namespace', 'eval', namespace, cmd, *args)
TkNamespace.new(namespace).eval(cmd, *args)
end
=begin
def eval(cmd = Proc.new, *args)
#TkNamespace.eval(@fullname, cmd, *args)
#ns_tk_call(cmd, *args)
code_obj = code(cmd)
ret = code_obj.call(*args)
# uninstall_cmd(TkCore::INTERP._split_tklist(code_obj.path)[-1])
uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
tk_tcl2ruby(ret)
end
=end
def eval(cmd = Proc.new, *args)
code_obj = code(cmd)
ret = code_obj.call(*args)
uninstall_cmd(_fromUTF8(TkCore::INTERP._split_tklist(_toUTF8(code_obj.path))[-1]))
ret
end
def self.exist?(ns)
bool(tk_call('namespace', 'exists', ns))
end
def exist?
TkNamespece.exist?(@fullname)
end
def self.export(*patterns)
tk_call('namespace', 'export', *patterns)
end
def self.export_with_clear(*patterns)
tk_call('namespace', 'export', '-clear', *patterns)
end
def export
TkNamespace.export(@fullname)
end
def export_with_clear
TkNamespace.export_with_clear(@fullname)
end
def self.forget(*patterns)
tk_call('namespace', 'forget', *patterns)
end
def forget
TkNamespace.forget(@fullname)
end
def self.import(*patterns)
tk_call('namespace', 'import', *patterns)
end
def self.force_import(*patterns)
tk_call('namespace', 'import', '-force', *patterns)
end
def import
TkNamespace.import(@fullname)
end
def force_import
TkNamespace.force_import(@fullname)
end
def self.inscope(namespace, script, *args)
tk_call('namespace', 'inscope', namespace, script, *args)
end
def inscope(script, *args)
TkNamespace.inscope(@fullname, script, *args)
end
def self.origin(cmd)
tk_call('namespace', 'origin', cmd)
end
def self.parent(namespace=None)
ns = tk_call('namespace', 'parent', namespace)
Tk_Namespace_ID_TBL.mutex.synchronize{
if Tk_Namespace_ID_TBL.key?(ns)
Tk_Namespace_ID_TBL[ns]
else
ns
end
}
end
def parent
tk_call('namespace', 'parent', @fullname)
end
def self.get_path
tk_call('namespace', 'path')
end
def self.set_path(*namespace_list)
tk_call('namespace', 'path', array2tk_list(namespace_list))
end
def set_path
tk_call('namespace', 'path', @fullname)
end
def self.qualifiers(str)
tk_call('namespace', 'qualifiers', str)
end
def self.tail(str)
tk_call('namespace', 'tail', str)
end
def self.upvar(namespace, *var_pairs)
tk_call('namespace', 'upvar', namespace, *(var_pairs.flatten))
end
def upvar(*var_pairs)
TkNamespace.inscope(@fullname, *(var_pairs.flatten))
end
def self.get_unknown_handler
tk_tcl2ruby(tk_call('namespace', 'unknown'))
end
def self.set_unknown_handler(cmd = Proc.new)
tk_call('namespace', 'unknown', cmd)
end
def self.which(name)
tk_call('namespace', 'which', name)
end
def self.which_command(name)
tk_call('namespace', 'which', '-command', name)
end
def self.which_variable(name)
tk_call('namespace', 'which', '-variable', name)
end
end
TkNamespace::Global = TkNamespace.new('::')