File indexing completed on 2024-04-21 04:35:50
0001 ## 0002 # This file is part of KDevelop 0003 # 0004 # Copyright (C) 2012-2015 Miquel Sabaté Solà <mikisabate@gmail.com> 0005 # 0006 # This program is free software: you can redistribute it and/or modify 0007 # it under the terms of the GNU General Public License as published by 0008 # the Free Software Foundation, either version 3 of the License, or 0009 # (at your option) any later version. 0010 # 0011 # This program is distributed in the hope that it will be useful, 0012 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 # GNU General Public License for more details. 0015 # 0016 # You should have received a copy of the GNU General Public License 0017 # along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 0019 0020 #!/usr/bin/env ruby 0021 0022 0023 # This script is the responsible of extracting all the info from the Ruby 0024 # source code (MRI) in order to generate a file containing all the builtin 0025 # modules, classes and methods. You should call this script like this: 0026 # 0027 # $ ruby kdevruby_doc.rb /absolute/path/to/mri builtins.rb 0028 # 0029 # This may take a while, but then you'll get a brand new builtins.rb file 0030 # containing all the Ruby's builtins. 0031 # 0032 # NOTE: Brace yourselves, this script is a complete hack. It re-opens 0033 # RDoc::RDoc and retrieves everything from it with black magic and unicorns. 0034 0035 0036 require 'rdoc/rdoc' 0037 0038 0039 # Re-open the RDoc::RDoc class. This way, we can extract all the info of 0040 # builtin classes, modules and methods. The method to be called is 0041 # RDoc::RDoc#parse_files that, in short parses all the given directory to 0042 # fetch info. After that, you can call the kdev_classes & kdev_modules methods 0043 # in order to retrieve hashes with all the extracted info. 0044 class RDoc::RDoc 0045 attr_reader :kdev_classes, :kdev_modules 0046 0047 # Public: Just call super and create a dummy value for @options. 0048 def initialize 0049 super 0050 @options = RDoc::Options.new 0051 @kdev_classes, @kdev_modules = {}, {} 0052 end 0053 0054 # Public: Re-implemented from RDoc::RDoc. Parse all the files from 0055 # a directory. 0056 # 0057 # directory - a String containing the path to the directory. 0058 def parse_files(directory) 0059 files = get_files_from directory 0060 @stats = RDoc::Stats.new files.size, @options.verbosity 0061 files.each { |f| parse_file(f) } 0062 end 0063 0064 # Public: Parse a file. 0065 # 0066 # name - a String containing the path to the file to be parsed. 0067 def parse_file(name) 0068 content = IO.read name 0069 top_level = RDoc::TopLevel.new name 0070 puts "Parsing: #{top_level.relative_name}" 0071 parser = RDoc::Parser.for top_level, name, content, @options, @stats 0072 return unless parser 0073 0074 parser.scan 0075 @kdev_classes = eclasses(top_level.classes_hash, @kdev_classes) 0076 @kdev_modules = emodules(top_level.modules_hash, @kdev_modules) 0077 end 0078 0079 private 0080 0081 # Internal: Get the files from the given directory. 0082 # 0083 # d - A String containing the given directory. 0084 # 0085 # Returns an Array containing all the files inside the given directory. 0086 def get_files_from(d) 0087 files = [] 0088 Dir.glob(File.join(d, '*.{c, rb}')).each { |f| files << f if File.file? f } 0089 files 0090 end 0091 0092 # Internal: Extract all the classes from the given parameters. 0093 # 0094 # hash - A Hash containing all the info on classes. 0095 # initial - A Hash containing calculations from previous calls. 0096 # 0097 # Returns a Hash containing the extracted results. 0098 def eclasses(hash, initial) 0099 final = initial || {} 0100 hash.each do |h| 0101 next if h.empty? 0102 h = h.last 0103 who = h.name.to_sym 0104 element = { comment: h.comment, ancestors: {} } 0105 ancestors = [] 0106 if h.superclass.nil? 0107 h.ancestors.each do |a| 0108 ancestors << (a.is_a? String) ? a.to_sym : a.name.to_sym 0109 end 0110 else 0111 base = (h.superclass.is_a? String) ? h.superclass : h.superclass.name 0112 element[:superclass] = base.to_sym 0113 who = (h.name == h.name.downcase) ? h.name.capitalize : h.name 0114 who = who.to_sym 0115 (h.ancestors - [h.superclass]).each do |a| 0116 if a.is_a? String 0117 ancestors << a.to_sym 0118 else 0119 ancestors << a.name.to_sym 0120 end 0121 end 0122 end 0123 if final.include? who 0124 final[who] = fmerge(final[who], ancestors, h) 0125 else 0126 element[:ancestors] = ancestors || {} 0127 element[:classes] = eclasses(h.classes_hash, {}) 0128 element[:methods] = emethods(h.methods_hash, {}) 0129 final[who] = element 0130 end 0131 end 0132 final 0133 end 0134 0135 # Internal: Extract all the modules from the given parameters. 0136 # 0137 # hash - A Hash containing all the info on modules. 0138 # initial - A Hash containing calculations from previous calls. 0139 # 0140 # Returns a Hash containing the extracted results. 0141 def emodules(hash, initial) 0142 final = initial || {} 0143 hash.each do |h| 0144 next if h.empty? 0145 h = h.last 0146 who = h.name.to_sym 0147 ancestors = h.ancestors.map { |a| a.name.to_sym } 0148 if final.include? who 0149 final[who] = fmerge(final[who], ancestors, h) 0150 else 0151 element = { comment: h.comment } 0152 element[:ancestors] = ancestors 0153 element[:classes] = eclasses(h.classes_hash, {}) 0154 element[:methods] = emethods(h.methods_hash, {}) 0155 final[who] = element 0156 end 0157 end 0158 final 0159 end 0160 0161 # Internal: Extract all the methods from the given parameters. 0162 # 0163 # hash - A Hash containing all the info on methods. 0164 # initial - A Hash containing calculations from previous calls. 0165 # 0166 # Returns a Hash containing the extracted results. 0167 def emethods(hash, initial) 0168 final = initial || {} 0169 hash.each do |m| 0170 method = m.last 0171 call_seq = method.call_seq 0172 unless call_seq.nil? 0173 call_seq.split(/\n\s*/).each { |k| final = get_method_string(method, k, final) } 0174 end 0175 end 0176 final 0177 end 0178 0179 # Internal: Extract all what we can from the call_seq string of a method. 0180 # 0181 # method - The method object from RDoc. 0182 # str - The call_seq string from the documentation of the method. 0183 # hash - A Hash containing calculations from previous calls. 0184 # 0185 # Returns a Hash containing the extracted results. 0186 def get_method_string(method, str, hash) 0187 final = hash || {} 0188 0189 # Extract block 0190 str = str.gsub(/\{(.+)\}/, '') 0191 block = !$1.nil? ? '&block' : nil 0192 str = str.gsub(/(\[\s*\])/, '') 0193 block = nil if !$1.nil? 0194 0195 # +per_se+ is the signature itself, and +ret+ the expected return type 0196 arrow = str.include?('=>') ? '=>' : '->' 0197 per_se, ret = str.split(arrow).map(&:strip) 0198 return final if per_se.nil? 0199 0200 # Extract name and arguments of the method 0201 name, args = per_se.split('(') 0202 name = name.split('.') 0203 name = if (name.size > 1) 0204 name.last 0205 else 0206 method.name 0207 end 0208 name = filter_name(name).to_sym 0209 0210 # Method arguments 0211 args_str = ''; 0212 if args.nil? 0213 args_str = "(#{block})" unless block.nil? 0214 if final.include? name 0215 if final[name][:args].split(',').size < args_str.split(',').size && method.singleton != final[name][:singleton] 0216 final[name][:args] = args_str 0217 end 0218 else 0219 final[name] = { comment: method.comment, args: args_str, singleton: method.singleton } 0220 end 0221 else 0222 # Separate between normal parameters and optional parameters ... 0223 args = args.chop.gsub(/\[(.+)\]/, '') 0224 opts = $1.scan(/\w+/) unless $1.nil? 0225 0226 # ... and join them again but now with the proper format. 0227 res = '' 0228 if args.empty? 0229 res = opts.join('=0, ') + '=0' unless opts.nil? 0230 else 0231 res = args.gsub(/nil/, 'null') 0232 res += ', ' + opts.join('=0, ') + '=0' unless opts.nil? 0233 end 0234 res = strip_reserved(res) 0235 res = fix_typos(res) 0236 if res.include?('arg*more') 0237 args_str = "(#{block})" 0238 elsif res =~ /\+|\*/ 0239 args_str = '()' 0240 else 0241 res.gsub!(' , string=0', 'string=0') 0242 res.gsub!(/filename=$/, "filename=''") 0243 args_str = block.nil? ? "(#{res})" : "(#{res}, #{block})" 0244 end 0245 0246 if final.include? name 0247 if final[name][:args].split(',').size < args_str.split(',').size && method.singleton != final[name][:singleton] 0248 final[name][:args] = args_str 0249 end 0250 else 0251 final[name] = { comment: method.comment, args: args_str, singleton: method.singleton } 0252 end 0253 end 0254 final[name][:return] = get_return(ret) 0255 final 0256 end 0257 0258 # Internal: Force merge. Forces the merge of internal hashes. 0259 # 0260 # element - The element to be updated. 0261 # ancestors - The ancestors of the given element. 0262 # h - The RDoc object of the Class/Module. 0263 # 0264 # Returns the same element but with some entries updated. 0265 def fmerge(element, ancestors, h) 0266 if element[:ancestors].nil? 0267 element[:ancestors] = ancestors 0268 else 0269 element[:ancestors] |= (ancestors) 0270 end 0271 if element[:classes].nil? 0272 element[:classes] = eclasses(h.classes_hash, element[:classes]) 0273 else 0274 element[:classes].merge!(eclasses(h.classes_hash, element[:classes])) 0275 end 0276 if element[:methods].nil? 0277 element[:methods] = emethods(h.methods_hash, element[:methods]) 0278 else 0279 element[:methods].merge!(emethods(h.methods_hash, element[:methods])) 0280 end 0281 element 0282 end 0283 0284 # Internal: The following are some methods to clean typos 0285 # from Ruby's documentation. 0286 # 0287 # Clean the given name. 0288 # 0289 # name - A String containing the name to clean. 0290 def filter_name(name) 0291 name = name.gsub(/(\w+) = (\w+)/) { "#{$1}= #{$2}" } 0292 name.gsub!('enc or nil', 'enc_or_nil') 0293 name.gsub!('proc_obj or nil', 'proc_or_nil') 0294 name = '[]' if name == ']' or name == ' ] ]' or name == '] ]' or name == ' ]' 0295 name 0296 end 0297 0298 # Internal: Fix random typos from the documentation by hand. 0299 # 0300 # res - A String containing the documentation to clean. 0301 def fix_typos(res) 0302 res.gsub!(/,\s*,/, ',') 0303 res.gsub!('"ext_enc:int_enc"', 'enc') 0304 res.gsub!('"root"', 'root') 0305 res.gsub!(/\w*: \w*/, 'random') 0306 res.gsub!(/\.\.\.?/, '*more') # arg1, ... => arg1, *more 0307 res.gsub!(/\+|\*/, '*more') 0308 res 0309 end 0310 0311 # Internal: Clean the given string from reserved words. 0312 # 0313 # str - The given string. 0314 def strip_reserved(str) 0315 str = str.gsub(/module/, 'modul').gsub(/class/, 'klass') 0316 str.gsub(/end/, '_end').gsub(/begin/, '_begin') 0317 end 0318 0319 # Internal: get the return value for a method. 0320 # NOTE: it has to be improved like a lot ... 0321 def get_return(ret) 0322 return nil if ret.nil? || ret.empty? 0323 { 0324 'anIO' => "''", 'obj' => 'Object.new', 'string' => "''", 0325 'integer' => '0', 'Numeric' => '0', 'array' => '[]', 'float' => '0.0', 0326 'true or false' => 'true || false', 'aBignum' => 'Bignum.new', 0327 'time' => 'Time.new', 'a_rational' => 'Rational.new', 'number' => '0', 0328 'numeric' => '0', 'fixnum' => '0', 'int' => '0', 0329 'new_time' => 'Time.new', 'new_str' => "''", 'str' => "''", 0330 'new_str or nil' => "'' || nil", 'an_enumerator' => 'Enumerator.new', 0331 '0 .. 255' => '0..255', 'anArray' => '[]', 'an_array' => '[]', 0332 'symbol' => ':a', 'enumerator' => 'Enumerator.new', 0333 '[head, match, tail]' => '[]', '[head, sep, tail]' => '[]', 0334 'sym' => ':a', 'other_symbol' => ':a', 'a_proc' => 'Proc.new', 0335 'encoding' => 'Encoding.new', 'char' => "''", 'prc' => 'Proc.new', 0336 'result_of_proc' => 'Proc.new', '[String, Fixnum]' => "['', 0]", 0337 'binding' => 'Binding.new', 'method' => 'Method.new', 0338 'new_method' => 'Method.new', 'unbound_method' => 'Method.new', 0339 'class_or_module' => 'Class.new || Module.new', 'self' => 'self', 0340 'a_binding' => 'Binding.new', 'rational' => 'Rational.new', 0341 '-1, 0, +1 or nil' => '1 || nil', '(0/1)' => '(0/1)', '1' => '1', 0342 'matchdata or nil' => 'MatchData.new || nil', 'object' => 'Object.new', 0343 'str or nil' => "'' || nil", 'fixnum or nil' => '1 || nil', 0344 'self or nil' => 'self || nil', 'proc' => 'Proc.new', 0345 'other_string' => "''", '$_' => '$_', 'hsh' => '{}', 'a_hash' => '{}', 0346 'Hash' => '{}', 'Enumerator' => 'Enumerator.new', 0347 'Array or nil' => '[] || nil', 'array or nil' => '[] || nil', 0348 'string or nil' => "'' || nil", '0' => '0', 'anObject' => 'Object.new', 0349 '(true or false)' => 'true || false', 'Integer' => '0', 0350 'new_hash' => '{}', 'hsh or new_hash' => '{}', 'real' => '0', 0351 'hash or nil' => '{} || nil', 'value' => 'Object.new', 0352 'numeric_result' => '0', 'integer or float' => '0 || 0.0', 0353 'an_exception or exc' => 'Exception.new', 'module' => 'Module.new', 0354 'aTime' => 'Time.new', 'abs_file_name' => "''", 'real_pathname' => "''", 0355 'base_name' => "''", 'ary' => '[]', '0 or false' => '0 || false', 0356 'obj or nil' => 'Object.new || nil', '0, 1' => '0', 0357 'enc' => 'Encoding.new', 'mod' => 'Module.new', 'rng' => '1..2', 0358 'num' => '0', 'integer_result' => '0', 'hsh_result' => '{}', 0359 'key' => 'Object.new', 'hash' => '{}', 'Array' => '[]', 0360 'anArray or obj' => '[] || Object.new', '"/home/me"' => "''", 0361 '"/root"' => "''", '[enc1, enc2, ...]' => '[Encoding.new]', 0362 '["enc1", "enc2", ...]' => '[Encoding.new]', 'new_ary' => '[]', 0363 'destination_string' => "''", 'dir' => 'Dir.new', 'aDir' => 'Dir.new', 0364 'exception or nil' => 'Exception.new || nil', 'enum' => 'Enumerator.new', 0365 'encoding or nil' => 'Encoding.new || nil', 'ARGF' => 'ARGF', 0366 'new_ary or nil' => '[] || nil', 'String' => "''", '0.0' => '0.0', 0367 'Integer or nil' => '0 || nil', 'file_name' => "''", 'dir_name' => "''", 0368 'path' => "''", 'stat' => "''", 'filename' => "''", 'false' => 'false', 0369 'outbuf' => "''", 'string, outbuf, or nil' => "'' || nil", '""' => "''", 0370 '{}' => '{}', '(0+0i)' => 'Complex.new', 0371 'complex' => 'Complex.new', 'Complex(0,num)' => 'Complex.new', 0372 '0 or float' => '0 || 0.0', 'other -> 0 or nil' => '0 || nil', 0373 'lazy_enum' => 'Enumerator::Lazy.new', 'thread' => 'Thread.new', 0374 'thr' => 'Thread.new', 'thr or nil' => 'nil || Thread.new', 0375 'true/false' => 'true || false', 'result of the block' => 'Object.new', 0376 '0 or nil' => '0 || nil', 'boolean' => 'true || false', 'io' => 'IO.new', 0377 'ios' => 'IO.new', 'array or nil' => '[] || nil', 'pid' => '0', 0378 '[read_io, write_io]' => '[IO.new]', 'io or nil' => 'IO.new || nil', 0379 'true' => 'true', 'String or nil' => "'' || nil", 0380 'obj or nil' => 'Object.new || nil', 'new_regexp' => '//', 0381 'lazy_enumerator' => 'Enumerator::Lazy.new', 'class' => 'Class.new', 0382 'matchdata' => 'MatchData.new', 're or nil' => '// || nil', 0383 'an_object' => 'Object.new', 'old_seed' => '1', 'struct' => 'Struct.new', 0384 'true, false or nil' => 'true || false || nil', 'regexp' => '//', 0385 'StructClass' => 'Struct.new', 'ary or nil' => '[] || nil', 0386 'ary or nil' => '[] || nil', 'obj or nil' => 'Object.new || nil', 0387 'obj or other_ary or nil' => '[] || nil', 'file' => 'File.new', 0388 'obj or nil' => 'Object.new || nil', 'int or nil' => '1 || nil', 0389 'nil, -1, +1' => '1 || nil', 'ARGV' => 'ARGV', 'IO' => 'IO', 0390 'Fixnum or nil' => '0 || nil', 'Fixnum' => '0', 'result' => 'Object.new', 0391 'integer or nil' => '1 || nil', '[name1, name2, ...]' => '[]', 0392 'signal_exception' => 'SignalException.new', 'elem' => 'Object.new', 0393 'other_module -> -1, 0, +1, or nil' => '1 || nil', 0394 'other -> 0 or nil' => '0 || nil', 'new_string' => "''", 0395 'true, false, or nil' => 'true || false || nil', 0396 'new_ary or nil' => '[]', 'aBinaryString' => "''", 0397 'other_string -> -1, 0, +1 or nil' => '1 || nil', 0398 '[pid, status]' => '[1]', 'prng' => 'Random.new', 0399 'system_exit' => 'SystemExit.new', 'name_error' => 'NameError.new', 0400 'no_method_error' => 'NoMethodError.new', 'hsh or nil' => '{} || nil', 0401 'an_array or nil' => '[] || nil', 'an_array or nil' => '[] || nil', 0402 'system_call_error_subclass' => 'SystemCallError', 0403 'ENV or nil' => 'ENV || nil', 'name' => "''", 0404 'real -> -1, 0, +1 or nil' => '1 || nil', 'e' => 'Exception.new', 0405 'numeric -> -1, 0, +1 or nil' => '1 || nil', 0406 'env' => 'ENV', '"ENV"' => 'ENV', 'enc or nil' => 'Encoding.new || nil', 0407 '[ fraction, exponent ]' => '[]', '[float, -1 or 1]' => '[0.0, 0]', 0408 'a_class' => 'Class.new', 'a_super_class or nil' => 'Class.new || nil', 0409 '"true"' => 'true', '!obj' => 'Object.new', '"false"' => 'false', 0410 'bool' => 'true || false', 'item or nil' => 'Object.new || nil', 0411 'item or result of block' => 'Object.new || nil', 0412 '[min, max]' => '[]', 'other_ary -> -1, 0, +1 or nil' => '1 || nil', 0413 'numeric -> -1, 0, +1 or nil' => '1 || nil', 0414 'other_time -> -1, 0, +1 or nil' => '1 || nil', 0415 'other_symbol -> -1, 0, +1 or nil' => '1 || nil', 0416 'a_string' => "''", 'exception' => 'Exception.new', 0417 'thgrp' => 'ThreadGroup.new', 'aStructTms' => 'Struct::Tms.new', 0418 'other_stat -> -1, 0, 1, nil' => '1 || nil', 0419 '[ [pid1,status1], ...]' => '[]', '[cur_limit, max_limit]' => '[]', 0420 'an_array_of_array' => '[]', '[obj, ...]' => '[]', 0421 'IO or File object' => 'IO.new || File.new', 'mutex' => 'Mutex.new', 0422 'other_stat -> -1, 0, 1, nil' => '1 || nil', 0423 'a_lazy_enumerator' => 'Enumerator::Lazy.new', 'fiber' => 'Fiber.new', 0424 'int, Float::INFINITY or nil' => '1 || 0.0 || nil', 0425 '[ true_array, false_array ]' => '[[true], [false]]', 0426 'string, false or nil' => "'' || false || nil", 0427 'thgrp or nil' => 'ThreadGroup.new || nil' 0428 }[ret] 0429 end 0430 end 0431 0432 # Re-open the File class so we can print the results of the RDoc::TopLevel's 0433 # hashes into files in an easier way. 0434 class File 0435 # Public: Print a comment. 0436 # 0437 # comment - A String containing the comment. 0438 def print_comment(comment) 0439 return if comment.empty? 0440 puts '##' 0441 puts comment.split("\n").each { |c| c.insert(0, '# ') << "\n" }.join 0442 end 0443 0444 # Public: Print all the modules. 0445 # 0446 # hash - A Hash containing all the info of all the modules. 0447 def print_modules(hash) 0448 hash.each do |k, v| 0449 print_comment v[:comment] 0450 puts "module #{k}" 0451 v[:ancestors].each { |m| puts "include #{m}" unless m.empty? } 0452 print_classes v[:classes] 0453 print_methods v[:methods] 0454 puts "end\n\n" 0455 end 0456 end 0457 0458 # Public: Print all the classes. 0459 # 0460 # hash - A Hash containing all the info of all the classes. 0461 def print_classes(hash) 0462 hash.each do |k, v| 0463 print_comment v[:comment] 0464 if v[:superclass].nil? 0465 puts "class #{k}" 0466 else 0467 puts "class #{k} < #{v[:superclass]}" 0468 end 0469 v[:ancestors].each { |m| puts "include #{m}" unless m.empty? } 0470 print_classes v[:classes] 0471 print_methods v[:methods] 0472 puts "end\n\n" 0473 end 0474 end 0475 0476 # Public: Print all the methods. 0477 # 0478 # hash - A Hash containing all the info of all the methods. 0479 def print_methods(hash) 0480 hash.each do |k, v| 0481 print_comment v[:comment] 0482 if v[:singleton] 0483 print "def self.#{k}" 0484 else 0485 print "def #{k}" 0486 end 0487 print v[:args] 0488 if !(k == :new && v[:singleton]) && !v[:return].nil? 0489 print "; #{v[:return]}" 0490 end 0491 puts "; end\n" 0492 end 0493 end 0494 end 0495 0496 0497 ## 0498 # Here starts the main program 0499 0500 0501 if ARGV.size != 2 0502 print <<-USAGE 0503 KDevelop Ruby Documentation generator. 0504 Usage: 0505 ruby kdevruby_doc.rb source_dir output_file 0506 USAGE 0507 exit 0508 end 0509 ruby_dir, ruby_out = ARGV 0510 0511 # Parse all the files contained inside the +ruby_dir+ directory. 0512 doc = RDoc::RDoc.new 0513 puts 'Generating documentation. Please be patient, this may take a while.' 0514 doc.parse_files ruby_dir 0515 0516 # Print everything into the +ruby_out+ file. 0517 output = File.open(ruby_out, 'w') 0518 ruby_version = File.open("#{ruby_dir}/version.h", &:readline) 0519 ruby_version.match(/\"(.+)\"/) 0520 output.puts <<HEADER 0521 ## 0522 # Ruby Version: #{$1} 0523 # This file is generated, all changes made in this file will be lost!\n\n 0524 HEADER 0525 output.print_modules doc.kdev_modules 0526 output.print_classes doc.kdev_classes 0527 0528 0529 # Print all the pre-defined global variables. 0530 { 0531 '$! = Exception.new' => "The exception information message set by 'raise'. ", 0532 "$@ = ['']" => 'Array of backtrace of the last exception thrown.', 0533 "$& = ''" => 'The string matched by the last successful match.', 0534 "$` = ''" => 'The string to the left of the last successful match.', 0535 "$' = ''" => 'The string to the right of the last successful match.', 0536 "$+ = ''" => 'The highest group matched by the last successful match.', 0537 '$~ = MatchData.new' => 'The information about the last match in the current scope.', 0538 '$= = true || false' => 'The flag for case insensitive, nil by default.', 0539 "$/ = ''" => 'The input record separator, newline by default.', 0540 "$\\ = ''"=> 'The output record separator for the print and IO#write. Default is nil.', 0541 "$, = ''" => 'The output field separator for the print and Array#join.', 0542 "$; = ''" => 'The default separator for String#split.', 0543 '$. = 0' => 'The current input line number of the last file that was read.', 0544 '$< = IO.new' => 'The virtual concatenation file of the files given on command line (or from $stdin if no files were given).', 0545 '$> = IO.new' => 'The default output for print, printf. $stdout by default.', 0546 "$_ = ''" => 'The last input line of string by gets or readline.', 0547 "$0 = ''" => 'Contains the name of the script being executed. May be assignable.', 0548 "$* = ['']" => 'Command line arguments given for the script sans args.', 0549 '$$ = 0' => 'The process number of the Ruby running this script.', 0550 '$? = 0' => 'The status of the last executed child process.', 0551 "$: = ['']" => 'Load path for scripts and binary modules by load or require.', 0552 "$\" = ['']" => 'The array contains the module names loaded by require.', 0553 '$DEBUG = true || false' => 'The status of the -d switch.', 0554 "$FILENAME = ''" => 'Current input file from $<. Same as $<.filename.', 0555 '$LOAD_PATH = $:' => 'The alias to the $:.', 0556 '$stderr = IO.new' => 'The current standard error output.', 0557 '$stdin = IO.new' => 'The current standard input.', 0558 '$stdout = IO.new' => 'The current standard output.', 0559 '$VERBOSE = true || false'=> 'The verbose flag, which is set by the -v switch.', 0560 '$-0 = $/' => 'The alias to $/.', 0561 '$-a = true || false' => 'True if option -a is set. Read-only variable.', 0562 '$-d = $DEBUG' => 'The alias to $DEBUG.', 0563 '$-F = $;' => 'The alias to $;.', 0564 '$-i = nil' => 'In in-place-edit mode, this variable holds the extension, otherwise nil.', 0565 '$-I = $:' => 'The alias to $:.', 0566 '$-l = true || false' => 'True if option -l is set. Read-only variable.', 0567 '$-p = true || false' => 'True if option -p is set. Read-only variable.', 0568 '$-v = $VERBOSE' => 'The alias to $VERBOSE.', 0569 '$-w = true || false' => 'True if option -w is set.' 0570 }.each { |k, v| output.puts "# #{v}\n#{k}\n\n" } 0571 0572 # Print all the pre-defined constants. 0573 { 0574 'TRUE = true' => 'The typical true value.', 0575 'FALSE = false' => 'The false itself.', 0576 'NIL = nil' => 'The nil itself.', 0577 'STDIN = $stdin' => 'The standard input. The default value for $stdin.', 0578 'STDOUT = $stdout' => 'The standard output. The default value for $stdout.', 0579 'STDERR = $stderr' => 'The standard error output. The default value for $stderr.', 0580 "ENV = {''=>''}" => 'The hash contains current environment variables.', 0581 'ARGF = $<' => 'The alias to the $<.', 0582 'ARGV = $*' => 'The alias to the $*.', 0583 'DATA = File.new' => 'The file object of the script, pointing just after __END__.', 0584 "RUBY_VERSION = ''" => 'The ruby version string (VERSION was deprecated).', 0585 "RUBY_RELEASE_DATE = ''" => 'The release date string.', 0586 "RUBY_PLATFORM = ''" => 'The platform identifier.' 0587 }.each { |k, v| output.puts "# #{v}\n#{k}\n\n" }