简体   繁体   中英

How to programmatically fetch ruby documentation of corelib / stdlib?

I have a big array. This array has all of ruby stdlib in like this format:

Array#size
Array#push
String#replace
String#<<

And so on. Now I wish to find the corresponding documentation of that method and give it back to the user. (It is like a cheap REPL, a mini irb if you so will - and I only need this mini functionality, nothing fully fledged.)

How could I find the part where Array#push is documented? I am fine using rdoc/yard/ri, I only need to get the docu from there in a string-form.

You can dig down into the RDoc documentation and access the Rdoc::RI::Driver code that ri uses, then play some games with how it outputs the data to capture what would normally go to the screen by using a StringIO object:

require 'rdoc'
require 'stringio'

ri = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args(%w[-T --format=ansi ]))
ri.use_stdout = true

ri_output = ''
$stdout = StringIO.new(ri_output)
ri.display_method('Array#push') 
$stdout = STDOUT

puts ri_output

Which results in:

[0m[1;32mArray#push[m

(from ruby core)
------------------------------------------------------------------------------
  ary.push(obj, ... )   -> ary

------------------------------------------------------------------------------

Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.

  a = [ "a", "b", "c" ]
  a.push("d", "e", "f")
          #=> ["a", "b", "c", "d", "e", "f"]
  [1, 2, 3,].push(4).push(5)
          #=> [1, 2, 3, 4, 5]

Change the output type to markdown to get output that doesn't use the ANSI terminal display codes:

ri = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args(%w[-T --format=markdown ]))

Which results in:

# Array#push

(from ruby core)
---
    ary.push(obj, ... )   -> ary

---

Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.

    a = [ "a", "b", "c" ]
    a.push("d", "e", "f")
            #=> ["a", "b", "c", "d", "e", "f"]
    [1, 2, 3,].push(4).push(5)
            #=> [1, 2, 3, 4, 5]

This little piece of magic allows us to capture the normal output that would go to STDOUT on the console into a string:

ri_output = ''
$stdout = StringIO.new(ri_output)

At that point, all normal STDOUT -based output will be stored in ri_output and not go to the console. Following that it's important to reassign STDOUT back to $stdout so puts output goes to the console again:

$stdout = STDOUT

It's probably possible to intercept the output prior to it going to the normal ri console output, but I didn't see a method, or way, for doing that that stood out.

I would use ri with a system call. For example

`ri Array#push`

returns

= Array#push

(from ruby core)
------------------------------------------------------------------------------
  ary.push(obj, ... )   -> ary

------------------------------------------------------------------------------

Append --- Pushes the given object(s) on to the end of this array. This
expression returns the array itself, so several appends may be chained
together. See also Array#pop for the opposite effect.

  a = [ "a", "b", "c" ]
  a.push("d", "e", "f")
          #=> ["a", "b", "c", "d", "e", "f"]
  [1, 2, 3,].push(4).push(5)
          #=> [1, 2, 3, 4, 5]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM