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