Extended maintenance of Ruby 1.9.3 ended on February 23, 2015. Read more
autoload
metric_type : default => num_or_str
option_type : default => string
system font names
# File tk/lib/tk/font.rb, line 205 def TkFont.actual(fnt, option=nil) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.actual(option) else actual_core(fnt, nil, option) end end
# File tk/lib/tk/font.rb, line 217 def TkFont.actual_displayof(fnt, win, option=nil) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.actual_displayof(win, option) else win = '.' unless win actual_core(fnt, win, option) end end
# File tk/lib/tk/font.rb, line 213 def TkFont.actual_hash(fnt, option=nil) Hash[TkFont.actual(fnt, option)] end
# File tk/lib/tk/font.rb, line 226 def TkFont.actual_hash_displayof(fnt, option=nil) Hash[TkFont.actual_displayof(fnt, option)] end
# File tk/lib/tk/font.rb, line 239 def TkFont.configinfo(fnt, slot=nil) if fnt.kind_of?(TkFont) fnt.configinfo(fnt, slot) else configinfo_core(fnt, slot) end end
# File tk/lib/tk/font.rb, line 230 def TkFont.configure(fnt, slot, value=None) if fnt.kind_of?(TkFont) fnt.configure(fnt, slot, value) else configure_core(fnt, slot, value) end fnt end
# File tk/lib/tk/font.rb, line 378 def TkFont.create_copy(font) fail 'source-font must be a TkFont object' unless font.kind_of? TkFont if TkComm::GET_CONFIGINFOwoRES_AS_ARRAY keys = {} font.configinfo.each{|key,value| keys[key] = value } TkFont.new(font.latin_font_id, font.kanji_font_id, keys) else # ! TkComm::GET_CONFIGINFOwoRES_AS_ARRAY TkFont.new(font.latin_font_id, font.kanji_font_id, font.configinfo) end end
# File tk/lib/tk/font.rb, line 247 def TkFont.current_configinfo(fnt, slot=nil) if fnt.kind_of?(TkFont) fnt.current_configinfo(fnt, slot) else current_configinfo_core(fnt, slot) end end
# File tk/lib/tk/font.rb, line 527 def TkFont.failsafe(font) begin if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK tk_call('font', 'failsafe', font) end rescue end end
# File tk/lib/tk/font.rb, line 347 def TkFont.families(win=nil) case (Tk::TK_VERSION) when /^4\..*/ ['fixed'] when /^8\..*/ if win tk_split_simplelist(tk_call('font', 'families', '-displayof', win)) else tk_split_simplelist(tk_call('font', 'families')) end end end
# File tk/lib/tk/font.rb, line 389 def TkFont.get_obj(name) name = name.to_s if name =~ /^(@font[0-9]+)(|c|l|k)$/ Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL[$1] } else Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL[name] } end end
# File tk/lib/tk/font.rb, line 402 def TkFont.init_widget_font(pathname, *args) win, tag, key = pathname.split(';') key = 'font' if key == nil || key == '' path = [win, tag, key].join(';') case (Tk::TK_VERSION) when /^4\..*/ regexp = /^-(|kanji)#{key} / conf_list = tk_split_simplelist(tk_call(*args)). find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} if conf_list.size == 0 raise RuntimeError, "the widget may not support 'font' option" end args << {} ltn_key = "-#{key}" knj_key = "-kanji#{key}" ltn_info = conf_list.find{|conf| conf[0] == ltn_key} ltn = ltn_info[-1] ltn = nil if ltn == [] || ltn == "" knj_info = conf_list.find{|conf| conf[0] == knj_key} knj = knj_info[-1] knj = nil if knj == [] || knj == "" TkFont.new(ltn, knj).call_font_configure([path, key], *args) when /^8\.[0-4]/ regexp = /^-#{key} / conf_list = tk_split_simplelist(tk_call(*args)). find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} if conf_list.size == 0 raise RuntimeError, "the widget may not support 'font' option" end args << {} optkey = "-#{key}" info = conf_list.find{|conf| conf[0] == optkey} fnt = info[-1] fnt = nil if fnt == [] || fnt == "" unless fnt # create dummy # TkFont.new(nil, nil).call_font_configure([path, key], *args) dummy_fnt = TkFont.allocate dummy_fnt.instance_eval{ init_dummy_fontobj() } dummy_fnt else begin compound = tk_split_simplelist( Hash[*tk_split_simplelist(tk_call('font', 'configure', fnt))].collect{|k,v| [k[1..-1], v] }.assoc('compound')[1]) rescue compound = [] end if compound == [] if TkFont.is_system_font?(fnt) TkNamedFont.new(fnt).call_font_configure([path, key], *args) else TkFont.new(fnt).call_font_configure([path, key], *args) end else TkFont.new(compound[0], compound[1]).call_font_configure([path, key], *args) end end when /^8\.[5-9]/, /^9\..*/ regexp = /^-#{key} / conf_list = tk_split_simplelist(tk_call(*args)). find_all{|prop| prop =~ regexp}. collect{|prop| tk_split_simplelist(prop)} if conf_list.size == 0 raise RuntimeError, "the widget may not support 'font' option" end args << {} optkey = "-#{key}" info = conf_list.find{|conf| conf[0] == optkey} fnt = info[-1] fnt = nil if fnt == [] || fnt == "" unless fnt # create dummy # TkFont.new(nil, nil).call_font_configure([path, key], *args) dummy_fnt = TkFont.allocate dummy_fnt.instance_eval{ init_dummy_fontobj() } dummy_fnt else if TkFont.is_system_font?(fnt) TkNamedFont.new(fnt).call_font_configure([path, key], *args) else TkFont.new(fnt).call_font_configure([path, key], *args) end end end end
class methods
# File tk/lib/tk/font.rb, line 197 def TkFont.is_system_font?(fnt) # true --> system font which is available on the current system # false --> not system font (or unknown system font) # nil --> system font name, but not available on the current system fnt = fnt.to_s SYSTEM_FONT_NAMES.include?(fnt) && self.names.index(fnt) && true end
# File tk/lib/tk/font.rb, line 255 def TkFont.measure(fnt, text) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.measure(text) else measure_core(fnt, nil, text) end end
# File tk/lib/tk/font.rb, line 264 def TkFont.measure_displayof(fnt, win, text) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.measure_displayof(win, text) else win = '.' unless win measure_core(fnt, win, text) end end
# File tk/lib/tk/font.rb, line 274 def TkFont.metrics(fnt, option=nil) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) fnt.metrics(option) else metrics_core(fnt, nil, option) end end
# File tk/lib/tk/font.rb, line 310 def TkFont.metrics_displayof(fnt, win, option=nil) fnt = '{}' if fnt == '' if fnt.kind_of?(TkFont) font.metrics_displayof(win, option=nil) else win = '.' unless win metrics_core(fnt, win, option) end end
# File tk/lib/tk/font.rb, line 282 def TkFont.metrics_hash(fnt, option=nil) if option val = TkFont.metrics(fnt, option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[TkFont.metrics(fnt)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 319 def TkFont.metrics_hash_displayof(fnt, win, option=nil) if option val = TkFont.metrics_displayof(fnt, win, option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[TkFont.metrics_displayof(fnt, win, option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 361 def TkFont.names case (Tk::TK_VERSION) when /^4\..*/ r = ['fixed'] r += ['a14', 'k14'] if JAPANIZED_TK Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL.each_value{|obj| r.push(obj)} } #r | [] r.uniq when /^8\..*/ tk_split_simplelist(tk_call('font', 'names')) end end
# File tk/lib/tk/font.rb, line 587 def initialize(ltn=nil, knj=nil, keys=nil) ltn = '{}' if ltn == '' knj = '{}' if knj == '' Tk_FontID.mutex.synchronize{ # @id = Tk_FontID.join('') @id = Tk_FontID.join(TkCore::INTERP._ip_id_) Tk_FontID[1].succ! } Tk_FontNameTBL.mutex.synchronize{ Tk_FontNameTBL[@id] = self } # @latin_desscendant = nil # @kanji_desscendant = nil @descendant = [nil, nil] # [latin, kanji] # @latinfont = @id + 'l' # @kanjifont = @id + 'k' # @compoundfont = @id + 'c' # @fontslot = {} if knj.kind_of?(Hash) && !keys keys = knj knj = nil end # compound font check if Tk::TK_VERSION == '8.0' && JAPANIZED_TK begin compound = tk_split_simplelist(tk_call('font', 'configure', ltn, '-compound')) if knj == nil if compound != [] ltn, knj = compound end else if compound != [] ltn = compound[0] end compound = tk_split_simplelist(tk_call('font', 'configure', knj, '-compound')) if compound != [] knj = compound[1] end end rescue end end if ltn if JAPANIZED_TK && !knj if Tk::TK_VERSION =~ /^4..*/ knj = DEFAULT_KANJI_FONT_NAME else knj = ltn end end else ltn = DEFAULT_LATIN_FONT_NAME knj = DEFAULT_KANJI_FONT_NAME if JAPANIZED_TK && !knj end create_compoundfont(ltn, knj, keys) end
# File tk/lib/tk/font.rb, line 1256 def [](slot) configinfo slot end
# File tk/lib/tk/font.rb, line 1260 def []=(slot, val) configure slot, val val end
# File tk/lib/tk/font.rb, line 1189 def actual(option=nil) actual_core(@compoundfont, nil, option) end
# File tk/lib/tk/font.rb, line 1196 def actual_displayof(win, option=nil) win = '.' unless win actual_core(@compoundfont, win, option) end
# File tk/lib/tk/font.rb, line 1192 def actual_hash(option=nil) Hash[actual(option)] end
# File tk/lib/tk/font.rb, line 1200 def actual_hash_displayof(win, option=nil) Hash[actual_displayof(win, option)] end
# File tk/lib/tk/font.rb, line 1040 def call_font_configure(path, *args) if path.kind_of?(Array) # [path, optkey] win, tag = path[0].split(';') optkey = path[1].to_s else win, tag, optkey = path.split(';') end fontslot = _symbolkey2str(@fontslot) if optkey && optkey != "" ltn = fontslot.delete('font') knj = fontslot.delete('kanjifont') fontslot[optkey] = ltn if ltn fontslot["kanji#{optkey}"] = knj if knj end keys = _symbolkey2str(args.pop).update(fontslot) args.concat(hash_kv(keys)) begin tk_call(*args) rescue => e unless TkConfigMethod.__IGNORE_UNKNOWN_CONFIGURE_OPTION__ fail e end end Tk_FontUseTBL.mutex.synchronize{ Tk_FontUseTBL[[win, tag, optkey].join(';')] = self } self end
# File tk/lib/tk/font.rb, line 1270 def configinfo(slot=nil) configinfo_core(@compoundfont, slot) end
# File tk/lib/tk/font.rb, line 1265 def configure(slot, value=None) configure_core(@compoundfont, slot, value) self end
# File tk/lib/tk/font.rb, line 1274 def current_configinfo(slot=nil) current_configinfo_core(@compoundfont, slot) end
# File tk/lib/tk/font.rb, line 1012 def inspect sprintf("#<%s:%0x:%s>", self.class.inspect, self.__id__, @compoundfont) end
# File tk/lib/tk/font.rb, line 1227 def kanji_actual(option=nil) #if JAPANIZED_TK if @kanjifont == nil actual_core(@compoundfont, nil, option) # use @compoundfont elsif @kanjifont != "" actual_core(@kanjifont, nil, option) else actual_core_tk4x(nil, nil, option) end end
# File tk/lib/tk/font.rb, line 1241 def kanji_actual_displayof(win, option=nil) #if JAPANIZED_TK if @kanjifont == nil actual_core(@compoundfont, nil, option) # use @compoundfont elsif @kanjifont != "" win = '.' unless win actual_core(@kanjifont, win, option) else actual_core_tk4x(nil, win, option) end end
# File tk/lib/tk/font.rb, line 1237 def kanji_actual_hash(option=nil) Hash[kanji_actual(option)] end
# File tk/lib/tk/font.rb, line 1252 def kanji_actual_hash_displayof(win, option=nil) Hash[kanji_actual_displayof(win, option)] end
# File tk/lib/tk/font.rb, line 1316 def kanji_configinfo(slot=nil) #if JAPANIZED_TK if @kanjifont == nil configure_core(@compoundfont, slot) # use @compoundfont elsif @kanjifont != "" configinfo_core(@kanjifont, slot) else #[] configinfo(slot) end end
# File tk/lib/tk/font.rb, line 1302 def kanji_configure(slot, value=None) #if JAPANIZED_TK if @kanjifont == nil configure_core(@compoundfont, slot, value) # use @compoundfont elsif @kanjifont != "" configure_core(@kanjifont, slot, value) configure('size'=>configinfo('size')) # to reflect new configuration else #"" configure(slot, value) end self end
# File tk/lib/tk/font.rb, line 1327 def kanji_current_configinfo(slot=nil) Hash[kanji_configinfo(slot)] end
# File tk/lib/tk/font.rb, line 1172 def kanji_font # @kanjifont if @descendant[1] # [1] -> kanji @descendant[1] else @descendant[1] = DescendantFont.new(self, 'kanji') end if @kanji_descendant @kanji_descendant else @kanji_descendant = DescendantFont.new(self, 'kanji') end end
# File tk/lib/tk/font.rb, line 1168 def kanji_font_id @kanjifont end
# File tk/lib/tk/font.rb, line 1511 def kanji_metrics(option=nil) if @latinfont == nil metrics_core(@compoundfont, nil, option) # use @compoundfont elsif JAPANIZED_TK metrics_core(@kanjifont, nil, option) else metrics_core_tk4x(nil, nil, option) end end
# File tk/lib/tk/font.rb, line 1548 def kanji_metrics_displayof(win, option=nil) win = '.' unless win if @latinfont == nil metrics_core(@compoundfont, win, option) # use @compoundfont elsif JAPANIZED_TK metrics_core(@kanjifont, win, option) else metrics_core_tk4x(nil, win, option) end end
# File tk/lib/tk/font.rb, line 1520 def kanji_metrics_hash(option=nil) if option val = kanji_metrics(option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[kanji_metrics(option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1558 def kanji_metrics_hash_displayof(win, option=nil) if option val = kanji_metrics_displayof(win, option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[kanji_metrics_displayof(win, option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1361 def kanji_replace(knj) return self unless @kanjifont # ignore kanji_replace_core(knj) reset_pointadjust self end
# File tk/lib/tk/font.rb, line 1204 def latin_actual(option=nil) if @latinfont == nil actual_core(@compoundfont, nil, option) # use @compoundfont else actual_core(@latinfont, nil, option) end end
# File tk/lib/tk/font.rb, line 1215 def latin_actual_displayof(win, option=nil) win = '.' unless win if @latinfont == nil actual_core(@compoundfont, win, option) # use @compoundfont else actual_core(@latinfont, win, option) end end
# File tk/lib/tk/font.rb, line 1211 def latin_actual_hash(option=nil) Hash[latin_actual(option)] end
# File tk/lib/tk/font.rb, line 1223 def latin_actual_hash_displayof(win, option=nil) Hash[latin_actual_displayof(win, option)] end
# File tk/lib/tk/font.rb, line 1291 def latin_configinfo(slot=nil) if JAPANIZED_TK configinfo_core(@latinfont, slot) else configinfo(slot) end end
# File tk/lib/tk/font.rb, line 1282 def latin_configure(slot, value=None) if JAPANIZED_TK configure_core(@latinfont, slot, value) else configure(slot, value) end self end
# File tk/lib/tk/font.rb, line 1298 def latin_current_configinfo(slot=nil) Hash[latin_configinfo(slot)] end
# File tk/lib/tk/font.rb, line 1151 def latin_font # @latinfont if @descendant[0] # [0] -> latin @descendant[0] else @descendant[0] = DescendantFont.new(self, 'latin') end if @latin_descendant @latin_descendant else @latin_descendant = DescendantFont.new(self, 'latin') end end
# File tk/lib/tk/font.rb, line 1147 def latin_font_id @latinfont end
# File tk/lib/tk/font.rb, line 1440 def latin_metrics(option=nil) if @latinfont == nil metrics_core(@compoundfont, nil, option) # use @compoundfont else metrics_core(@latinfont, nil, option) end end
# File tk/lib/tk/font.rb, line 1475 def latin_metrics_displayof(win, option=nil) win = '.' unless win if @latinfont == nil metrics_core(@compoundfont, win, option) # use @compoundfont else metrics_core(@latinfont, win, option) end end
# File tk/lib/tk/font.rb, line 1447 def latin_metrics_hash(option=nil) if option val = latin_metrics(option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[latin_metrics(option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1483 def latin_metrics_hash_displayof(win, option=nil) if option val = latin_metrics_displayof(win, option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[latin_metrics_displayof(win, option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1338 def latin_replace(ltn) if @latinfont latin_replace_core(ltn) reset_pointadjust else # not compound font -> copy properties of ltn latinkeys = {} begin actual_core(ltn).each{|key,val| latinkeys[key] = val} rescue latinkeys = {} end begin tk_call('font', 'configure', @compoundfont, *hash_kv(latinkeys)) rescue # not exist? (deleted?) -> create font tk_call('font', 'create', @compoundfont, *hash_kv(latinkeys)) end end self end
# File tk/lib/tk/font.rb, line 1368 def measure(text) measure_core(@compoundfont, nil, text) end
# File tk/lib/tk/font.rb, line 1372 def measure_displayof(win, text) win = '.' unless win measure_core(@compoundfont, win, text) end
# File tk/lib/tk/font.rb, line 1016 def method_missing(id, *args) name = id.id2name case args.length when 1 if name[-1] == ?= configure name[0..-2], args[0] args[0] else configure name, args[0] self end when 0 begin configinfo name rescue super(id, *args) # fail NameError, "undefined local variable or method `#{name}' for #{self.to_s}", error_at end else super(id, *args) # fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at end end
# File tk/lib/tk/font.rb, line 1377 def metrics(option=nil) metrics_core(@compoundfont, nil, option) end
# File tk/lib/tk/font.rb, line 1408 def metrics_displayof(win, option=nil) win = '.' unless win metrics_core(@compoundfont, win, option) end
# File tk/lib/tk/font.rb, line 1380 def metrics_hash(option=nil) if option val = metrics(option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[metrics(option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1412 def metrics_hash_displayof(win, option=nil) if option val = metrics_displayof(win, option) case TkFont::MetricsType[option.to_s] when ?n val = TkComm::num_or_str(val) when ?b val = TkComm::bool(val) else # do nothing end return val end h = Hash[metrics_displayof(win, option)] h.keys.each{|k| case TkFont::MetricsType[k.to_s] when ?n h[k] = TkComm::num_or_str(h[k]) when ?b h[k] = TkComm::bool(h[k]) else # do nothing end } h end
# File tk/lib/tk/font.rb, line 1331 def replace(ltn, knj=None) knj = ltn if knj == None latin_replace(ltn) kanji_replace(knj) self end
# File tk/lib/tk/font.rb, line 1586 def reset_pointadjust begin if /^8\..*/ === Tk::TK_VERSION && JAPANIZED_TK configure('pointadjust' => latin_actual.assoc('size')[1].to_f / kanji_actual.assoc('size')[1].to_f ) end rescue end self end
# File tk/lib/tk/font.rb, line 1072 def used ret = [] table = nil Tk_FontUseTBL.mutex.synchronize{ table = Tk_FontUseTBL.clone # to avoid deadlock } table.each{|key,value| next unless self == value if key.include?(';') win, tag, optkey = key.split(';') winobj = tk_tcl2ruby(win) #if winobj.kind_of? TkText if winobj.kind_of?(TkText) || winobj.kind_of?(Tk::Text) if optkey ret.push([winobj, winobj.tagid2obj(tag), optkey]) else ret.push([winobj, winobj.tagid2obj(tag)]) end #elsif winobj.kind_of? TkCanvas elsif winobj.kind_of?(TkCanvas) || winobj.kind_of?(Tk::Canvas) if (tagobj = TkcTag.id2obj(winobj, tag)).kind_of? TkcTag if optkey ret.push([winobj, tagobj, optkey]) else ret.push([winobj, tagobj]) end elsif (tagobj = TkcItem.id2obj(winobj, tag)).kind_of? TkcItem if optkey ret.push([winobj, tagobj, optkey]) else ret.push([winobj, tagobj]) end else if optkey ret.push([winobj, tag, optkey]) else ret.push([winobj, tag]) end end #elsif winobj.kind_of? TkMenu elsif winobj.kind_of?(TkMenu) || winobj.kind_of?(Tk::Menu) if optkey ret.push([winobj, tag, optkey]) else ret.push([winobj, tag]) end else if optkey ret.push([win, tag, optkey]) else ret.push([win, tag]) end end else ret.push(tk_tcl2ruby(key)) end } ret end
Commenting is here to help enhance the documentation. For example, code samples, or clarification of the documentation.
If you have questions about Ruby or the documentation, please post to one of the Ruby mailing lists. You will get better, faster, help that way.
If you wish to post a correction of the docs, please do so, but also file bug report so that it can be corrected for the next release. Thank you.
If you want to help improve the Ruby documentation, please visit Documenting-ruby.org.