Increasing ri's searching capibilities and some handy snippets

Hi rubyheads,
  I'm new to the ruby community and am fascinated with its power,simplicity and clean syntax!
Coming from the perl world where there never seemed to be a standard for documentation subroutines,
I'm amazed with the ri command for providing such fine-grained searching of classes and their
methods. Being a search freak, there are still more ways I'd like to be able to search
ruby classes,files ,methods and variables. Since I got a lot of questions about rdoc/ri is this
something I should take to the ruby-core mailing list? If so skip to question 2.

1. Extending ri search functions

  - Display code for a subroutine by extracting it from its file.
    I've seen this functionally in html form at http://www.ruby-doc.org/stdlib/
    but I don't know how long it'll take to extract the relevant subroutines to do
    this from the commandline.
  - Display documentation for all instance methods of a class at once.
    I do this so I can quickly flip and search through to learn how to use a class. Currently
    this one-liner works for classes loaded by default. But it would be much handier
    if I knew how to map any class to its file (from rdoc generated info) to require the
    relevant file.

ri `ruby -e 'print Object.const_get(ARGV[0].to_s).instance_methods(nil).sort.collect! {|x| ARGV[0]+"."
+x }.join(" ")' Array`

  - See modules and classes and their methods defined by filename.
    See the sample ruby_file_parser.rb code I've pasted at the end of this email.

  -Backending ri's searching functions to a database for speed and flexibility in searching.
    Any such efforts to import

2. If I want to contribute handy snippets of code is the rubyforge.org snippet section the place to
go?
Doesn't seem that it gets much traffic. If I think some snippet is really handy and should come
distributed with ruby in its sample/ directory who do I mention this to?

For example, at the end there's a handy snippet, path.rb, I use daily to locate ruby files matching a given regular
expression.

Thanks,
Gabriel

##path.rb
require 'find'
require 'optparse'
OPT = {
        :verbose=>false,
        :gemdir=>false
}

def parseARGV
        ARGV.options do |opts|
          script_name = File.basename($0)
          opts.banner = "Usage: #{script_name} [options] search_term"

         opts.separator ""

        opts.on("-g",'--gemdir',"Include gemdir"
                ) {|OPT[:gemdir] |}
        opts.on("-v", "--verbose", "Verbose output","Default: false"
                  ) { |OPT[:verbose] |}

          opts.on("-h", "--help",
                  "Show this help message.") { puts opts; exit }

          opts.parse!
        end
end

files =[]
parseARGV
file = ARGV.shift or raise "No file given"
GEMDIR = '/usr/local/lib/ruby/gems'
#or generate with `gem environment gempath`
searchdir = $:
searchdir.push(GEMDIR) if OPT[:gemdir]
searchdir.delete('.')
i = 0

Find.find(*searchdir) do |f|
        puts "#{i}:#{f}" if OPT[:verbose]
        files.push(f) if f =~ /\/#{file}\.(so|rb)$/
        i+=1
end
puts files.uniq
__END__

##ruby_file_parser.rb
require 'rdoc/options.rb'
require 'rdoc/rdoc.rb'
require 'rdoc/code_objects.rb'
require 'rdoc/parsers/parse_rb.rb'
require 'yaml'

#redefined this subroutine cause the commented out section was throwing a bizarre '*' not defined
error
class RubyLex
class BufferedReader
        def initialize(content)
                if /\t/ =~ content
                tab_width = Options.instance.tab_width
                #content = content.split(/\n/).map do |line|
                # 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length %
tab_width)} && $~ #`
                # line
                # end .join("\n")
                end
                @content = content
                @content << "\n" unless @content[-1,1] == "\n"
                @size = @content.size
                @offset = 0
                @hwm = 0
                @line_num = 1
                @read_back_offset = 0
                @last_newline = 0
                @newline_pending = false
        end
end
end

$final = {}
def index_class(cls)
        class_name = cls.full_name
        $final[class_name] = cls.method_list.map {|x| x.name } if ! $final[class_name]
        cls.each_classmodule { |x| index_class(x) }
end

file = ARGV.shift or raise "no file given"
content = File.open(file, "r") {|f| f.read}
#P = RDoc::RubyParser.new(RDoc::TopLevel.new(file),file,content,Options.instance,RDoc::Stats.new)
P =
RDoc::ParserFactory.parser_for(RDoc::TopLevel.new(file),file,content,Options.instance,RDoc::Stats.new)
P.scan
rclasses = RDoc::TopLevel.all_classes_and_modules
classes = rclasses.map {|x| x.full_name }

for rc in rclasses
        index_class(rc)
end

puts YAML::dump($final)
__END__

···

--
my looovely website -- http://www.chwhat.com
BTW, IF chwhat.com goes down email me at gabriel.horner@cern.ch

Its possible to use parsetree and some associated code posted on
http://blog.zenspider.com/archives/ruby/ to display the code for a
function (as sexp, ruby or c, no less).

http://raa.ruby-lang.org/ is a good place to put bits of code.

···

On Fri, 25 Feb 2005 13:57:59 +0900, Gabriel Horner <cldwalker@chwhat.com> wrote:

Hi rubyheads,
  I'm new to the ruby community and am fascinated with its power,simplicity and clean syntax!
Coming from the perl world where there never seemed to be a standard for documentation subroutines,
I'm amazed with the ri command for providing such fine-grained searching of classes and their
methods. Being a search freak, there are still more ways I'd like to be able to search
ruby classes,files ,methods and variables. Since I got a lot of questions about rdoc/ri is this
something I should take to the ruby-core mailing list? If so skip to question 2.

1. Extending ri search functions

        - Display code for a subroutine by extracting it from its file.
                I've seen this functionally in html form at RDoc Documentation
                but I don't know how long it'll take to extract the relevant subroutines to do
                this from the commandline.
        - Display documentation for all instance methods of a class at once.
                I do this so I can quickly flip and search through to learn how to use a class. Currently
                this one-liner works for classes loaded by default. But it would be much handier
                if I knew how to map any class to its file (from rdoc generated info) to require the
                relevant file.

ri `ruby -e 'print Object.const_get(ARGV[0].to_s).instance_methods(nil).sort.collect! {|x| ARGV[0]+"."
+x }.join(" ")' Array`

        - See modules and classes and their methods defined by filename.
                See the sample ruby_file_parser.rb code I've pasted at the end of this email.

        -Backending ri's searching functions to a database for speed and flexibility in searching.
                Any such efforts to import

2. If I want to contribute handy snippets of code is the rubyforge.org snippet section the place to
go?
Doesn't seem that it gets much traffic. If I think some snippet is really handy and should come
distributed with ruby in its sample/ directory who do I mention this to?

For example, at the end there's a handy snippet, path.rb, I use daily to locate ruby files matching a given regular
expression.

Thanks,
Gabriel

##path.rb
require 'find'
require 'optparse'
OPT = {
        :verbose=>false,
        :gemdir=>false
}

def parseARGV
        ARGV.options do |opts|
          script_name = File.basename($0)
          opts.banner = "Usage: #{script_name} [options] search_term"

         opts.separator ""

        opts.on("-g",'--gemdir',"Include gemdir"
                ) {|OPT[:gemdir] |}
        opts.on("-v", "--verbose", "Verbose output","Default: false"
                  ) { |OPT[:verbose] |}

          opts.on("-h", "--help",
                  "Show this help message.") { puts opts; exit }

          opts.parse!
        end
end

files =
parseARGV
file = ARGV.shift or raise "No file given"
GEMDIR = '/usr/local/lib/ruby/gems'
#or generate with `gem environment gempath`
searchdir = $:
searchdir.push(GEMDIR) if OPT[:gemdir]
searchdir.delete('.')
i = 0

Find.find(*searchdir) do |f|
        puts "#{i}:#{f}" if OPT[:verbose]
        files.push(f) if f =~ /\/#{file}\.(so|rb)$/
        i+=1
end
puts files.uniq
__END__

##ruby_file_parser.rb
require 'rdoc/options.rb'
require 'rdoc/rdoc.rb'
require 'rdoc/code_objects.rb'
require 'rdoc/parsers/parse_rb.rb'
require 'yaml'

#redefined this subroutine cause the commented out section was throwing a bizarre '*' not defined
error
class RubyLex
class BufferedReader
        def initialize(content)
                if /\t/ =~ content
                tab_width = Options.instance.tab_width
                #content = content.split(/\n/).map do |line|
                # 1 while line.gsub!(/\t+/) { ' ' * (tab_width*$&.length - $`.length %
tab_width)} && $~ #`
                # line
                # end .join("\n")
                end
                @content = content
                @content << "\n" unless @content[-1,1] == "\n"
                @size = @content.size
                @offset = 0
                @hwm = 0
                @line_num = 1
                @read_back_offset = 0
                @last_newline = 0
                @newline_pending = false
        end
end
end

$final = {}
def index_class(cls)
        class_name = cls.full_name
        $final[class_name] = cls.method_list.map {|x| x.name } if ! $final[class_name]
        cls.each_classmodule { |x| index_class(x) }
end

file = ARGV.shift or raise "no file given"
content = File.open(file, "r") {|f| f.read}
#P = RDoc::RubyParser.new(RDoc::TopLevel.new(file),file,content,Options.instance,RDoc::Stats.new)
P =
RDoc::ParserFactory.parser_for(RDoc::TopLevel.new(file),file,content,Options.instance,RDoc::Stats.new)
P.scan
rclasses = RDoc::TopLevel.all_classes_and_modules
classes = rclasses.map {|x| x.full_name }

for rc in rclasses
        index_class(rc)
end

puts YAML::dump($final)
__END__

--
my looovely website -- http://www.chwhat.com
BTW, IF chwhat.com goes down email me at gabriel.horner@cern.ch

--
spooq