当前位置: 首页 > 工具软件 > FXRI > 使用案例 >

新版RubyGems导致fxri/ri不能检索Gem的Doc的解决方法

郤立果
2023-12-01

    今天在Ruby上装了Win32API的Gem,想在fxri中看一下有哪些模块,却发现列表里没有出现,网上找了半天也没找到原因。最后花了2个小时看了fxri、ri和RubyGems的源码,终于找到了原因。

    新的RubyGems在返回Gem.path给的是一个数组,而ri中认为Gem.path是一个字符串而生成了一个不存在的搜索路径,因此找不到Gem的Doc。

    因此我修改了ri中的代码,使其支持新版RubyGems的Gem.path方法。

文件名:ri_paths.rb

原始代码:

  1. GEMDIRS = Dir["#{Gem.path}/doc/*/ri"]
  2. GEMDIRS.each { |path| RI::Paths::PATH << path }

修改好的代码:

  1. GEMDIRS = Gem.path.dup
  2. GEMDIRS.length.times{ |n|
  3. GEMDIRS[n] = Dir["#{GEMDIRS[n]}/doc/*/ri"]
  4.     GEMDIRS[n].each { |path| RI::Paths::PATH << path }
  5.     }

文件名:ri_options.rb

原始代码:

第一部分:

  1. (RI::Paths::GEMDIRS ? "#{Gem.path}/doc/*/ri" :
  2.                       No Rubygems ri found.") ],

第二部分:

  1. directories << "#{Gem.path}/doc/*/ri" if RI::Paths::GEMDIRS

修改好的代码:

第一部分:

  1. (RI::Paths::GEMDIRS ? "#{Gem.path.inject(""){ |strall,strpath| strall += strpath + "/n  "} }":
  2.                                 "No Rubygems ri found.") ],

第二部分:

  1. Gem.path.each{ |path| directories << "#{path}/doc/*/ri"     if RI::Paths::GEMDIRS}

 

修改好的完整文件如下:

文件下载地址:http://download.csdn.net/source/929228

ri_paths.rb

  1. module RI
  2.   # Encapsulate all the strangeness to do with finding out
  3.   # where to find RDoc files
  4.   #
  5.   # We basically deal with three directories:
  6.   #
  7.   # 1. The 'system' documentation directory, which holds
  8.   #    the documentation distributed with Ruby, and which
  9.   #    is managed by the Ruby install process
  10.   # 2. The 'site' directory, which contains site-wide
  11.   #    documentation added locally.
  12.   # 3. The 'user' documentation directory, stored under the
  13.   #    user's own home directory.
  14.   #
  15.   # There's contention about all this, but for now:
  16.   #
  17.   # system:: $datadir/ri/<ver>/system/...
  18.   # site::   $datadir/ri/<ver>/site/...
  19.   # user::   ~/.rdoc
  20.   module Paths
  21.     #:stopdoc:
  22.     require 'rbconfig'
  23.     
  24.     DOC_DIR  = "doc/rdoc"
  25.     version = Config::CONFIG['ruby_version']
  26.     base    = File.join(Config::CONFIG['datadir'], "ri", version)
  27.     SYSDIR  = File.join(base, "system")
  28.     SITEDIR = File.join(base, "site")
  29.     homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
  30.     if homedir
  31.       HOMEDIR = File.join(homedir, ".rdoc")
  32.     else
  33.       HOMEDIR = nil
  34.     end
  35.     # This is the search path for 'ri'
  36.     PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
  37.     begin
  38.       require 'rubygems'
  39.       #GEMDIRS = Dir["#{Gem.path}/doc/*/ri"]
  40.       #GEMDIRS.each { |path| RI::Paths::PATH << path }
  41.       #Change For New RubyGems
  42.       GEMDIRS = Gem.path.dup
  43.       GEMDIRS.length.times{ |n|
  44.         GEMDIRS[n] = Dir["#{GEMDIRS[n]}/doc/*/ri"]
  45.         GEMDIRS[n].each { |path| RI::Paths::PATH << path }
  46.         }
  47.     rescue LoadError
  48.       GEMDIRS = nil
  49.     end
  50.     # Returns the selected documentation directories as an Array, or PATH if no
  51.     # overriding directories were given.
  52.     def self.path(use_system, use_site, use_home, use_gems, *extra_dirs)
  53.       path = raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
  54.       return path.select { |path| File.directory? path }
  55.     end
  56.     # Returns the selected documentation directories including nonexistent
  57.     # directories.  Used to print out what paths were searched if no ri was
  58.     # found.
  59.     def self.raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
  60.       return PATH unless use_system or use_site or use_home or use_gems or
  61.                          not extra_dirs.empty?
  62.       path = []
  63.       path << extra_dirs unless extra_dirs.empty?
  64.       path << RI::Paths::SYSDIR if use_system
  65.       path << RI::Paths::SITEDIR if use_site
  66.       path << RI::Paths::HOMEDIR if use_home
  67.       path << RI::Paths::GEMDIRS if use_gems
  68.       return path.flatten.compact
  69.     end
  70.   end
  71. end

ri_options.rb文件

  1. # We handle the parsing of options, and subsequently as a singleton
  2. # object to be queried for option values
  3. module RI
  4.   require 'rdoc/ri/ri_paths'
  5.   require 'rdoc/ri/ri_display'
  6.   VERSION_STRING = "ri v1.0.1 - 20041108"
  7.   class Options
  8.     
  9.     require 'singleton'
  10.     require 'getoptlong'
  11.     
  12.     include Singleton
  13.     # No not use a pager. Writable, because ri sets it if it
  14.     # can't find a pager
  15.     attr_accessor :use_stdout
  16.     # should we just display a class list and exit
  17.     attr_reader :list_classes
  18.     # should we display a list of all names
  19.     attr_reader :list_names
  20.     # The width of the output line
  21.     attr_reader :width
  22.     # the formatting we apply to the output
  23.     attr_reader :formatter
  24.     # the directory we search for original documentation
  25.     attr_reader :doc_dir
  26.     module OptionList
  27.       
  28.       OPTION_LIST = [
  29.         [ "--help",          "-h",   nil,
  30.           "you're looking at it" ],
  31.         [ "--classes",      "-c",   nil,
  32.           "Display the names of classes and modules we/n" +
  33.           "know about"],
  34.         [ "--doc-dir",      "-d",   "<dirname>",
  35.           "A directory to search for documentation. If not/n" +
  36.           "specified, we search the standard rdoc/ri directories./n" +
  37.           "May be repeated."],
  38.         [ "--system",       nil,    nil,
  39.           "Include documentation from Ruby's standard library:/n  " +
  40.           RI::Paths::SYSDIR ],
  41.         [ "--site",         nil,    nil,
  42.           "Include documentation from libraries installed in site_lib:/n  " +
  43.           RI::Paths::SITEDIR ],
  44.         [ "--home",         nil,    nil,
  45.           "Include documentation stored in ~/.rdoc:/n  " +
  46.           (RI::Paths::HOMEDIR || "No ~/.rdoc found") ],
  47.         [ "--gems",         nil,    nil,
  48.           "Include documentation from Rubygems:/n  " +
  49.           (RI::Paths::GEMDIRS ? "#{Gem.path.inject(""){ |strall,strpath| strall += strpath + "/n  "} }":
  50.                                 "No Rubygems ri found.") ],
  51.                                                            
  52.         [ "--format",       "-f",   "<name>",
  53.           "Format to use when displaying output:/n" +
  54.           "   " + RI::TextFormatter.list + "/n" +
  55.           "Use 'bs' (backspace) with most pager programs./n" +
  56.           "To use ANSI, either also use the -T option, or/n" +
  57.           "tell your pager to allow control characters/n" +
  58.           "(for example using the -R option to less)"],
  59.         [ "--list-names",    "-l",   nil,
  60.           "List all the names known to RDoc, one per line"
  61.         ],
  62.         [ "--no-pager",      "-T",   nil,
  63.           "Send output directly to stdout." 
  64.         ],
  65.         [ "--width",         "-w",   "output width",
  66.         "Set the width of the output" ],
  67.         [ "--version",       "-v",   nil,
  68.          "Display the version of ri"
  69.         ],
  70.       ]
  71.       def OptionList.options
  72.         OPTION_LIST.map do |long, short, arg,|
  73.           option = []
  74.           option << long
  75.           option << short unless short.nil?
  76.           option << (arg ? GetoptLong::REQUIRED_ARGUMENT :
  77.                            GetoptLong::NO_ARGUMENT)
  78.           option
  79.         end
  80.       end
  81.       def OptionList.strip_output(text)
  82.         text =~ /^/s+/
  83.         leading_spaces = $
  84.         text.gsub!(/^#{leading_spaces}/, '')
  85.         $stdout.puts text
  86.       end
  87.       
  88.       
  89.       # Show an error and exit
  90.       
  91.       def OptionList.error(msg)
  92.         $stderr.puts
  93.         $stderr.puts msg
  94.         $stderr.puts "/nFor help on options, try 'ri --help'/n/n"
  95.         exit 1
  96.       end
  97.       
  98.       # Show usage and exit
  99.       
  100.       def OptionList.usage(short_form=false)
  101.         
  102.         puts
  103.         puts(RI::VERSION_STRING)
  104.         puts
  105.         
  106.         name = File.basename($0)
  107.         directories = [
  108.           RI::Paths::SYSDIR,
  109.           RI::Paths::SITEDIR,
  110.           RI::Paths::HOMEDIR
  111.         ]
  112.         Gem.path.each{ |path| directories << "#{path}/doc/*/ri"     if RI::Paths::GEMDIRS}
  113.         directories = directories.join("/n    ")
  114.         OptionList.strip_output(<<-EOT)
  115.           Usage:
  116.             #{name} [options]  [names...]
  117.           Display information on Ruby classes, modules, and methods.
  118.           Give the names of classes or methods to see their documentation.
  119.           Partial names may be given: if the names match more than
  120.           one entity, a list will be shown, otherwise details on
  121.           that entity will be displayed.
  122.           Nested classes and modules can be specified using the normal
  123.           Name::Name notation, and instance methods can be distinguished
  124.           from class methods using "." (or "#") instead of "::".
  125.           For example:
  126.               ri  File
  127.               ri  File.new
  128.               ri  F.n
  129.               ri  zip
  130.           Note that shell quoting may be required for method names
  131.           containing punctuation:
  132.               ri 'Array.[]'
  133.               ri compact//!
  134.           By default ri searches for documentation in the following
  135.           directories:
  136.               #{directories}
  137.           Specifying the --system, --site, --home, --gems or --doc-dir
  138.           options will limit ri to searching only the specified
  139.           directories.
  140.         EOT
  141.         if short_form
  142.           puts "For help on options, type 'ri -h'"
  143.           puts "For a list of classes I know about, type 'ri -c'"
  144.         else
  145.           puts "Options:/n/n"
  146.           OPTION_LIST.each do|long, short, arg, desc|
  147.             opt = ''
  148.             opt << (short ? sprintf("%15s""#{long}, #{short}") :
  149.                             sprintf("%15s", long))
  150.             if arg
  151.               opt << " " << arg
  152.             end
  153.             print opt
  154.             desc = desc.split("/n")
  155.             if opt.size < 17
  156.               print " "*(18-opt.size)
  157.               puts desc.shift
  158.             else
  159.               puts
  160.             end
  161.             desc.each do |line|
  162.               puts(" "*18 + line)
  163.             end
  164.             puts
  165.           end
  166.           puts "Options may also be passed in the 'RI' environment variable"
  167.           exit 0
  168.         end
  169.       end
  170.     end
  171.     # Show the version and exit
  172.     def show_version
  173.       puts VERSION_STRING
  174.       exit(0)
  175.     end
  176.     def initialize
  177.       @use_stdout   = !STDOUT.tty?
  178.       @width        = 72
  179.       @formatter    = RI::TextFormatter.for("plain"
  180.       @list_classes = false
  181.       @list_names   = false
  182.       # By default all paths are used.  If any of these are true, only those
  183.       # directories are used.
  184.       @use_system = false
  185.       @use_site = false
  186.       @use_home = false
  187.       @use_gems = false
  188.       @doc_dirs = []
  189.     end
  190.     # Parse command line options.
  191.     def parse(args)
  192.     
  193.       old_argv = ARGV.dup
  194.       ARGV.replace(args)
  195.       begin
  196.         go = GetoptLong.new(*OptionList.options)
  197.         go.quiet = true
  198.         go.each do |opt, arg|
  199.           case opt
  200.           when "--help"       then OptionList.usage
  201.           when "--version"    then show_version
  202.           when "--list-names" then @list_names = true
  203.           when "--no-pager"   then @use_stdout = true
  204.           when "--classes"    then @list_classes = true
  205.           when "--system"     then @use_system = true
  206.           when "--site"       then @use_site = true
  207.           when "--home"       then @use_home = true
  208.           when "--gems"       then @use_gems = true
  209.           when "--doc-dir"
  210.             if File.directory?(arg)
  211.               @doc_dirs << arg
  212.             else
  213.               $stderr.puts "Invalid directory: #{arg}"
  214.               exit 1
  215.             end
  216.           when "--format"
  217.             @formatter = RI::TextFormatter.for(arg)
  218.             unless @formatter
  219.               $stderr.print "Invalid formatter (should be one of "
  220.               $stderr.puts RI::TextFormatter.list + ")"
  221.               exit 1
  222.             end
  223.           when "--width"
  224.             begin
  225.               @width = Integer(arg)
  226.             rescue 
  227.               $stderr.puts "Invalid width: '#{arg}'"
  228.               exit 1
  229.             end
  230.           end
  231.         end
  232.       rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument => error
  233.         OptionList.error(error.message)
  234.       end
  235.     end
  236.     # Return the selected documentation directories.
  237.     def path
  238.       RI::Paths.path(@use_system@use_site@use_home@use_gems, *@doc_dirs)
  239.     end
  240.     def raw_path
  241.       RI::Paths.raw_path(@use_system@use_site@use_home@use_gems,
  242.                          *@doc_dirs)
  243.     end
  244.     # Return an instance of the displayer (the thing that actually writes
  245.     # the information). This allows us to load in new displayer classes
  246.     # at runtime (for example to help with IDE integration)
  247.     
  248.     def displayer
  249.       ::RiDisplay.new(self)
  250.     end
  251.   end
  252. end
 类似资料: