1require 'rdoc/ri'
2
3##
4# The directories where ri data lives.  Paths can be enumerated via ::each, or
5# queried individually via ::system_dir, ::site_dir, ::home_dir and ::gem_dir.
6
7module RDoc::RI::Paths
8
9  #:stopdoc:
10  require 'rbconfig'
11
12  version = RbConfig::CONFIG['ruby_version']
13
14  BASE    = if RbConfig::CONFIG.key? 'ridir' then
15              File.join RbConfig::CONFIG['ridir'], version
16            else
17              File.join RbConfig::CONFIG['datadir'], 'ri', version
18            end
19
20  homedir = begin
21              File.expand_path('~')
22            rescue ArgumentError
23            end
24
25  homedir ||= ENV['HOME'] ||
26              ENV['USERPROFILE'] || ENV['HOMEPATH'] # for 1.8 compatibility
27
28  HOMEDIR = if homedir then
29              File.join homedir, ".rdoc"
30            end
31  #:startdoc:
32
33  ##
34  # Iterates over each selected path yielding the directory and type.
35  #
36  # Yielded types:
37  # :system:: Where Ruby's ri data is stored.  Yielded when +system+ is
38  #           true
39  # :site:: Where ri for installed libraries are stored.  Yielded when
40  #         +site+ is true.  Normally no ri data is stored here.
41  # :home:: ~/.rdoc.  Yielded when +home+ is true.
42  # :gem:: ri data for an installed gem.  Yielded when +gems+ is true.
43  # :extra:: ri data directory from the command line.  Yielded for each
44  #          entry in +extra_dirs+
45
46  def self.each system = true, site = true, home = true, gems = :latest, *extra_dirs # :yields: directory, type
47    return enum_for __method__, system, site, home, gems, *extra_dirs unless
48      block_given?
49
50    extra_dirs.each do |dir|
51      yield dir, :extra
52    end
53
54    yield system_dir,  :system if system
55    yield site_dir,    :site   if site
56    yield home_dir,    :home   if home and HOMEDIR
57
58    gemdirs(gems).each do |dir|
59      yield dir, :gem
60    end if gems
61
62    nil
63  end
64
65  ##
66  # The ri directory for the gem with +gem_name+.
67
68  def self.gem_dir name, version
69    req = Gem::Requirement.new "= #{version}"
70
71    spec = Gem::Specification.find_by_name name, req
72
73    File.join spec.doc_dir, 'ri'
74  end
75
76  ##
77  # The latest installed gems' ri directories.  +filter+ can be :all or
78  # :latest.
79  #
80  # A +filter+ :all includes all versions of gems and includes gems without
81  # ri documentation.
82
83  def self.gemdirs filter = :latest
84    require 'rubygems' unless defined?(Gem)
85
86    ri_paths = {}
87
88    all = Gem::Specification.map do |spec|
89      [File.join(spec.doc_dir, 'ri'), spec.name, spec.version]
90    end
91
92    if filter == :all then
93      gemdirs = []
94
95      all.group_by do |_, name, _|
96        name
97      end.sort_by do |group, _|
98        group
99      end.map do |group, items|
100        items.sort_by do |_, _, version|
101          version
102        end.reverse_each do |dir,|
103          gemdirs << dir
104        end
105      end
106
107      return gemdirs
108    end
109
110    all.each do |dir, name, ver|
111      next unless File.exist? dir
112
113      if ri_paths[name].nil? or ver > ri_paths[name].first then
114        ri_paths[name] = [ver, name, dir]
115      end
116    end
117
118    ri_paths.sort_by { |_, (_, name, _)| name }.map { |k, v| v.last }
119  rescue LoadError
120    []
121  end
122
123  ##
124  # The location of the rdoc data in the user's home directory.
125  #
126  # Like ::system, ri data in the user's home directory is rare and predates
127  # libraries distributed via RubyGems.  ri data is rarely generated into this
128  # directory.
129
130  def self.home_dir
131    HOMEDIR
132  end
133
134  ##
135  # Returns existing directories from the selected documentation directories
136  # as an Array.
137  #
138  # See also ::each
139
140  def self.path(system = true, site = true, home = true, gems = :latest, *extra_dirs)
141    path = raw_path system, site, home, gems, *extra_dirs
142
143    path.select { |directory| File.directory? directory }
144  end
145
146  ##
147  # Returns selected documentation directories including nonexistent
148  # directories.
149  #
150  # See also ::each
151
152  def self.raw_path(system, site, home, gems, *extra_dirs)
153    path = []
154
155    each(system, site, home, gems, *extra_dirs) do |dir, type|
156      path << dir
157    end
158
159    path.compact
160  end
161
162  ##
163  # The location of ri data installed into the site dir.
164  #
165  # Historically this was available for documentation installed by ruby
166  # libraries predating RubyGems.  It is unlikely to contain any content for
167  # modern ruby installations.
168
169  def self.site_dir
170    File.join BASE, 'site'
171  end
172
173  ##
174  # The location of the built-in ri data.
175  #
176  # This data is built automatically when `make` is run when ruby is
177  # installed.  If you did not install ruby by hand you may need to install
178  # the documentation yourself.  Please consult the documentation for your
179  # package manager or ruby installer for details.  You can also use the
180  # rdoc-data gem to install system ri data for common versions of ruby.
181
182  def self.system_dir
183    File.join BASE, 'system'
184  end
185
186end
187
188