testdoc 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,607 @@
1
+ # We handle the parsing of options, and subsequently as a singleton
2
+ # object to be queried for option values
3
+
4
+ require "rdoc/ri/ri_paths"
5
+
6
+ class Options
7
+
8
+ require 'singleton'
9
+ require 'getoptlong'
10
+
11
+ include Singleton
12
+
13
+ # files matching this pattern will be excluded
14
+ attr_accessor :exclude
15
+
16
+ # the name of the output directory
17
+ attr_accessor :op_dir
18
+
19
+ # the name to use for the output
20
+ attr_reader :op_name
21
+
22
+ # include private and protected methods in the
23
+ # output
24
+ attr_accessor :show_all
25
+
26
+ # name of the file, class or module to display in
27
+ # the initial index page (if not specified
28
+ # the first file we encounter is used)
29
+ attr_accessor :main_page
30
+
31
+ # merge into classes of the name name when generating ri
32
+ attr_reader :merge
33
+
34
+
35
+
36
+ # merge into classes of the name name when generating ri
37
+ attr_reader :text
38
+
39
+
40
+ # Don't display progress as we process the files
41
+ attr_reader :quiet
42
+
43
+ # description of the output generator (set with the <tt>-fmt</tt>
44
+ # option
45
+ attr_accessor :generator
46
+
47
+ # and the list of files to be processed
48
+ attr_reader :files
49
+
50
+ # array of directories to search for files to satisfy an :include:
51
+ attr_reader :rdoc_include
52
+
53
+ attr_reader :debug
54
+ attr_accessor :debug
55
+
56
+ # title to be used out the output
57
+ attr_writer :title
58
+
59
+ # template to be used when generating output
60
+ attr_reader :template
61
+
62
+ # should diagrams be drawn
63
+ attr_reader :diagram
64
+
65
+ # should we draw fileboxes in diagrams
66
+ attr_reader :fileboxes
67
+
68
+ # include the '#' at the front of hyperlinked instance method names
69
+ attr_reader :show_hash
70
+
71
+ # image format for diagrams
72
+ attr_reader :image_format
73
+
74
+ # character-set
75
+ attr_reader :charset
76
+
77
+ # should source code be included inline, or displayed in a popup
78
+ attr_reader :inline_source
79
+
80
+ # should the output be placed into a single file
81
+ attr_reader :all_one_file
82
+
83
+ # the number of columns in a tab
84
+ attr_reader :tab_width
85
+
86
+ # include line numbers in the source listings
87
+ attr_reader :include_line_numbers
88
+
89
+ # pattern for additional attr_... style methods
90
+ attr_reader :extra_accessors
91
+ attr_reader :extra_accessor_flags
92
+
93
+ # URL of stylesheet
94
+ attr_reader :css
95
+
96
+ # URL of web cvs frontend
97
+ attr_reader :webcvs
98
+
99
+ # Are we promiscuous about showing module contents across
100
+ # multiple files
101
+ attr_reader :promiscuous
102
+
103
+ # scan newer sources than the flag file if true.
104
+ attr_reader :force_update
105
+
106
+ module OptionList
107
+
108
+ OPTION_LIST = [
109
+ # [ "--accessor", "-A", "accessorname[,..]",
110
+ # "comma separated list of additional class methods\n" +
111
+ # "that should be treated like 'attr_reader' and\n" +
112
+ # "friends. Option may be repeated. Each accessorname\n" +
113
+ # "may have '=text' appended, in which case that text\n" +
114
+ # "appears where the r/w/rw appears for normal accessors."],
115
+
116
+ # [ "--all", "-a", nil,
117
+ # "include all methods (not just public)\nin the output" ],
118
+
119
+ # [ "--charset", "-c", "charset",
120
+ # "specifies HTML character-set" ],
121
+
122
+ [ "--debug", "-D", nil,
123
+ "displays testplan in compact format" ],
124
+
125
+ # [ "--diagram", "-d", nil,
126
+ # "Generate diagrams showing modules and classes.\n" +
127
+ # "You need dot V1.8.6 or later to use the --diagram\n" +
128
+ # "option correctly. Dot is available from\n"+
129
+ # "http://www.research.att.com/sw/tools/graphviz/" ],
130
+
131
+ # [ "--exclude", "-x", "pattern",
132
+ # "do not process files or directories matching\n" +
133
+ # "pattern. Files given explicitly on the command\n" +
134
+ # "line will never be excluded." ],
135
+
136
+ # [ "--extension", "-E", "new=old",
137
+ # "Treat files ending with .new as if they ended with\n" +
138
+ # ".old. Using '-E cgi=rb' will cause xxx.cgi to be\n" +
139
+ # "parsed as a Ruby file"],
140
+
141
+ # [ "--fileboxes", "-F", nil,
142
+ # "classes are put in boxes which represents\n" +
143
+ # "files, where these classes reside. Classes\n" +
144
+ # "shared between more than one file are\n" +
145
+ # "shown with list of files that sharing them.\n" +
146
+ # "Silently discarded if --diagram is not given\n" +
147
+ # "Experimental." ],
148
+
149
+ # [ "--force-update", "-U", nil,
150
+ # "forces to scan all sources even if newer than\n" +
151
+ # "the flag file." ],
152
+
153
+ [ "--fmt", "-f", "format name",
154
+ "set the output formatter (see below)" ],
155
+
156
+ [ "--help", "-h", nil,
157
+ "you're looking at it" ],
158
+
159
+ # [ "--help-output", "-O", nil,
160
+ # "explain the various output options" ],
161
+
162
+ # [ "--image-format", "-I", "gif/png/jpg/jpeg",
163
+ # "Sets output image format for diagrams. Can\n" +
164
+ # "be png, gif, jpeg, jpg. If this option is\n" +
165
+ # "omitted, png is used. Requires --diagram." ],
166
+
167
+ # [ "--include", "-i", "dir[,dir...]",
168
+ # "set (or add to) the list of directories\n" +
169
+ # "to be searched when satisfying :include:\n" +
170
+ # "requests. Can be used more than once." ],
171
+
172
+ # [ "--inline-source", "-S", nil,
173
+ # "Show method source code inline, rather\n" +
174
+ # "than via a popup link" ],
175
+
176
+ # [ "--line-numbers", "-N", nil,
177
+ # "Include line numbers in the source code" ],
178
+
179
+ # [ "--main", "-m", "name",
180
+ # "'name' will be the initial page displayed" ],
181
+
182
+ [ "--merge", "-M", nil,
183
+ "when creating ri output, merge processed classes\n" +
184
+ "into previously documented classes of the name name"],
185
+
186
+ [ "--text", "-x", nil,
187
+ "text output to stdout instead of html"],
188
+
189
+ # [ "--one-file", "-1", nil,
190
+ # "put all the output into a single file" ],
191
+
192
+ # [ "--op", "-o", "dir",
193
+ # "set the output directory" ],
194
+
195
+ # [ "--opname", "-n", "name",
196
+ # "Set the 'name' of the output. Has no\n" +
197
+ # "effect for HTML." ],
198
+
199
+ # [ "--promiscuous", "-p", nil,
200
+ # "When documenting a file that contains a module\n" +
201
+ # "or class also defined in other files, show\n" +
202
+ # "all stuff for that module/class in each files\n" +
203
+ # "page. By default, only show stuff defined in\n" +
204
+ # "that particular file." ],
205
+
206
+ [ "--quiet", "-q", nil,
207
+ "don't show progress as we parse" ],
208
+
209
+ # [ "--ri", "-r", nil,
210
+ # "generate output for use by 'ri.' The files are\n" +
211
+ # "stored in the '.rdoc' directory under your home\n"+
212
+ # "directory unless overridden by a subsequent\n" +
213
+ # "--op parameter, so no special privileges are needed." ],
214
+
215
+ # [ "--ri-site", "-R", nil,
216
+ # "generate output for use by 'ri.' The files are\n" +
217
+ # "stored in a site-wide directory, making them accessible\n"+
218
+ # "to others, so special privileges are needed." ],
219
+
220
+ # [ "--ri-system", "-Y", nil,
221
+ # "generate output for use by 'ri.' The files are\n" +
222
+ # "stored in a system-level directory, making them accessible\n"+
223
+ # "to others, so special privileges are needed. This option\n"+
224
+ # "is intended to be used during Ruby installations" ],
225
+
226
+ # [ "--show-hash", "-H", nil,
227
+ # "A name of the form #name in a comment\n" +
228
+ # "is a possible hyperlink to an instance\n" +
229
+ # "method name. When displayed, the '#' is\n" +
230
+ # "removed unless this option is specified" ],
231
+
232
+ # [ "--style", "-s", "stylesheet url",
233
+ # "specifies the URL of a separate stylesheet." ],
234
+
235
+ # [ "--tab-width", "-w", "n",
236
+ # "Set the width of tab characters (default 8)"],
237
+
238
+ # [ "--template", "-T", "template name",
239
+ # "Set the template used when generating output" ],
240
+
241
+ [ "--title", "-t", "text",
242
+ "Set 'txt' as the title for the output" ],
243
+
244
+ [ "--version", "-v", nil,
245
+ "display TestDoc's version" ]
246
+
247
+ # [ "--webcvs", "-W", "url",
248
+ # "Specify a URL for linking to a web frontend\n" +
249
+ # "to CVS. If the URL contains a '\%s', the\n" +
250
+ # "name of the current file will be substituted;\n" +
251
+ # "if the URL doesn't contain a '\%s', the\n" +
252
+ # "filename will be appended to it." ],
253
+
254
+ ]
255
+
256
+ def OptionList.options
257
+ OPTION_LIST.map do |long, short, arg,|
258
+ [ long,
259
+ short,
260
+ arg ? GetoptLong::REQUIRED_ARGUMENT : GetoptLong::NO_ARGUMENT
261
+ ]
262
+ end
263
+ end
264
+
265
+
266
+ def OptionList.strip_output(text)
267
+ text =~ /^\s+/
268
+ leading_spaces = $&
269
+ text.gsub!(/^#{leading_spaces}/, '')
270
+ $stdout.puts text
271
+ end
272
+
273
+
274
+ # Show an error and exit
275
+
276
+ def OptionList.error(msg)
277
+ $stderr.puts
278
+ $stderr.puts msg
279
+ $stderr.puts "\nFor help on options, try 'testdoc --help'\n\n"
280
+ exit 1
281
+ end
282
+
283
+ # Show usage and exit
284
+
285
+ def OptionList.usage(generator_names)
286
+
287
+ puts
288
+ puts(VERSION_STRING)
289
+ puts
290
+
291
+ name = File.basename($0)
292
+ OptionList.strip_output(<<-EOT)
293
+ Usage:
294
+
295
+ #{name} [options] [names...]
296
+
297
+ Generates test documentation from sourcecode comments.
298
+ These directives are extracted from the sourcecode:
299
+
300
+ # testplan: Title for testplan (Optional)
301
+ # test: What to test
302
+ # task: How to perform the test manually
303
+ # check: How to perform the check (Optional)
304
+
305
+ Directives can be multiline and have to be in the
306
+ correct order as shown above. If a name is a directory,
307
+ it is traversed. If no names are specified, all
308
+ Ruby files in the current directory (and subdirectories) are
309
+ processed.
310
+
311
+ Options:
312
+
313
+ EOT
314
+
315
+ OPTION_LIST.each do |long, short, arg, desc|
316
+ opt = sprintf("%20s", "#{long}, #{short}")
317
+ oparg = sprintf("%-7s", arg)
318
+ print "#{opt} #{oparg}"
319
+ desc = desc.split("\n")
320
+ if arg.nil? || arg.length < 7
321
+ puts desc.shift
322
+ else
323
+ puts
324
+ end
325
+ desc.each do |line|
326
+ puts(" "*28 + line)
327
+ end
328
+ puts
329
+ end
330
+
331
+ # puts "\nAvailable output formatters: " +
332
+ # generator_names.sort.join(', ') + "\n\n"
333
+
334
+ # puts "For information on where the output goes, use\n\n"
335
+ # puts " rdoc --help-output\n\n"
336
+
337
+ exit 0
338
+ end
339
+
340
+ def OptionList.help_output
341
+ OptionList.strip_output(<<-EOT)
342
+ How RDoc generates output depends on the output formatter being
343
+ used, and on the options you give.
344
+
345
+ - HTML output is normally produced into a number of separate files
346
+ (one per class, module, and file, along with various indices).
347
+ These files will appear in the directory given by the --op
348
+ option (doc/ by default).
349
+
350
+ - XML output by default is written to standard output. If a
351
+ --opname option is given, the output will instead be written
352
+ to a file with that name in the output directory.
353
+
354
+ - .chm files (Windows help files) are written in the --op directory.
355
+ If an --opname parameter is present, that name is used, otherwise
356
+ the file will be called rdoc.chm.
357
+
358
+ For information on other RDoc options, use "rdoc --help".
359
+ EOT
360
+ exit 0
361
+ end
362
+ end
363
+
364
+ # Parse command line options. We're passed a hash containing
365
+ # output generators, keyed by the generator name
366
+
367
+ def parse(argv, generators)
368
+ old_argv = ARGV.dup
369
+ begin
370
+ ARGV.replace(argv)
371
+ @op_dir = "doc"
372
+ @op_name = nil
373
+ @show_all = false
374
+ @main_page = nil
375
+ @marge = false
376
+ @exclude = []
377
+ @quiet = false
378
+ @generator_name = 'html'
379
+ @generator = generators[@generator_name]
380
+ @rdoc_include = []
381
+ @title = nil
382
+ @template = nil
383
+ @diagram = false
384
+ @fileboxes = false
385
+ @show_hash = false
386
+ @image_format = 'png'
387
+ @inline_source = false
388
+ @all_one_file = false
389
+ @tab_width = 8
390
+ @include_line_numbers = false
391
+ @extra_accessor_flags = {}
392
+ @promiscuous = false
393
+ @force_update = false
394
+
395
+ @css = nil
396
+ @webcvs = nil
397
+
398
+ @charset = case $KCODE
399
+ when /^S/i
400
+ 'Shift_JIS'
401
+ when /^E/i
402
+ 'EUC-JP'
403
+ else
404
+ 'iso-8859-1'
405
+ end
406
+
407
+ accessors = []
408
+
409
+ go = GetoptLong.new(*OptionList.options)
410
+ go.quiet = true
411
+
412
+ go.each do |opt, arg|
413
+ case opt
414
+ # when "--all" then @show_all = true
415
+ # when "--charset" then @charset = arg
416
+ when "--debug" then $DEBUG = true
417
+ # when "--exclude" then @exclude << Regexp.new(arg)
418
+ # when "--inline-source" then @inline_source = true
419
+ # when "--line-numbers" then @include_line_numbers = true
420
+ # when "--main" then @main_page = arg
421
+ when "--merge" then @merge = true
422
+ when "--text" then @text = true
423
+ # when "--one-file" then @all_one_file = @inline_source = true
424
+ # when "--op" then @op_dir = arg
425
+ # when "--opname" then @op_name = arg
426
+ # when "--promiscuous" then @promiscuous = true
427
+ when "--quiet" then @quiet = true
428
+ when "--show-hash" then @show_hash = true
429
+ when "--style" then @css = arg
430
+ when "--template" then @template = arg
431
+ when "--title" then @title = arg
432
+ when "--webcvs" then @webcvs = arg
433
+
434
+ when "--accessor"
435
+ arg.split(/,/).each do |accessor|
436
+ if accessor =~ /^(\w+)(=(.*))?$/
437
+ accessors << $1
438
+ @extra_accessor_flags[$1] = $3
439
+ end
440
+ end
441
+
442
+ when "--diagram"
443
+ check_diagram
444
+ @diagram = true
445
+
446
+ when "--fileboxes"
447
+ @fileboxes = true if @diagram
448
+
449
+ when "--fmt"
450
+ @generator_name = arg.downcase
451
+ setup_generator(generators)
452
+
453
+ when "--help"
454
+ OptionList.usage(generators.keys)
455
+
456
+ when "--help-output"
457
+ OptionList.help_output
458
+
459
+ when "--image-format"
460
+ if ['gif', 'png', 'jpeg', 'jpg'].include?(arg)
461
+ @image_format = arg
462
+ else
463
+ raise GetoptLong::InvalidOption.new("unknown image format: #{arg}")
464
+ end
465
+
466
+ when "--include"
467
+ @rdoc_include.concat arg.split(/\s*,\s*/)
468
+
469
+ when "--ri", "--ri-site", "--ri-system"
470
+ @generator_name = "ri"
471
+ @op_dir = case opt
472
+ when "--ri" then RI::Paths::HOMEDIR
473
+ when "--ri-site" then RI::Paths::SITEDIR
474
+ when "--ri-system" then RI::Paths::SYSDIR
475
+ else fail opt
476
+ end
477
+ setup_generator(generators)
478
+
479
+ when "--tab-width"
480
+ begin
481
+ @tab_width = Integer(arg)
482
+ rescue
483
+ $stderr.puts "Invalid tab width: '#{arg}'"
484
+ exit 1
485
+ end
486
+
487
+ when "--extension"
488
+ new, old = arg.split(/=/, 2)
489
+ OptionList.error("Invalid parameter to '-E'") unless new && old
490
+ unless RDoc::ParserFactory.alias_extension(old, new)
491
+ OptionList.error("Unknown extension .#{old} to -E")
492
+ end
493
+
494
+ when "--force-update"
495
+ @force_update = true
496
+
497
+ when "--version"
498
+ puts VERSION_STRING
499
+ exit
500
+ end
501
+
502
+ end
503
+
504
+ @files = ARGV.dup
505
+
506
+ @rdoc_include << "." if @rdoc_include.empty?
507
+
508
+ if @exclude.empty?
509
+ @exclude = nil
510
+ else
511
+ @exclude = Regexp.new(@exclude.join("|"))
512
+ end
513
+
514
+ check_files
515
+
516
+ # If no template was specified, use the default
517
+ # template for the output formatter
518
+
519
+ @template ||= @generator_name
520
+
521
+ # Generate a regexp from the accessors
522
+ unless accessors.empty?
523
+ re = '^(' + accessors.map{|a| Regexp.quote(a)}.join('|') + ')$'
524
+ @extra_accessors = Regexp.new(re)
525
+ end
526
+
527
+ rescue GetoptLong::InvalidOption, GetoptLong::MissingArgument => error
528
+ OptionList.error(error.message)
529
+
530
+ ensure
531
+ ARGV.replace(old_argv)
532
+ end
533
+ end
534
+
535
+
536
+ def title
537
+ @title ||= "TestDoc"
538
+ end
539
+
540
+ # Set the title, but only if not already set. This means that a title set from
541
+ # the command line trumps one set in a source file
542
+
543
+ def title=(string)
544
+ @title ||= string
545
+ end
546
+
547
+
548
+ private
549
+
550
+ # Set up an output generator for the format in @generator_name
551
+ def setup_generator(generators)
552
+ # @generator = generators[@generator_name]
553
+ # if !@generator
554
+ # OptionList.error("Invalid output formatter")
555
+ # end
556
+
557
+ if @generator_name == "xml"
558
+ @all_one_file = true
559
+ @inline_source = true
560
+ end
561
+ end
562
+
563
+ # Check that the right version of 'dot' is available.
564
+ # Unfortuately this doesn't work correctly under Windows NT,
565
+ # so we'll bypass the test under Windows
566
+
567
+ def check_diagram
568
+ return if RUBY_PLATFORM =~ /win/
569
+
570
+ ok = false
571
+ ver = nil
572
+ IO.popen("dot -V 2>&1") do |io|
573
+ ver = io.read
574
+ if ver =~ /dot.+version(?:\s+gviz)?\s+(\d+)\.(\d+)/
575
+ ok = ($1.to_i > 1) || ($1.to_i == 1 && $2.to_i >= 8)
576
+ end
577
+ end
578
+ unless ok
579
+ if ver =~ /^dot.+version/
580
+ $stderr.puts "Warning: You may need dot V1.8.6 or later to use\n",
581
+ "the --diagram option correctly. You have:\n\n ",
582
+ ver,
583
+ "\nDiagrams might have strange background colors.\n\n"
584
+ else
585
+ $stderr.puts "You need the 'dot' program to produce diagrams.",
586
+ "(see http://www.research.att.com/sw/tools/graphviz/)\n\n"
587
+ exit
588
+ end
589
+ # exit
590
+ end
591
+ end
592
+
593
+ # Check that the files on the command line exist
594
+
595
+ def check_files
596
+ @files.each do |f|
597
+ stat = File.stat f rescue error("File not found: #{f}")
598
+ error("File '#{f}' not readable") unless stat.readable?
599
+ end
600
+ end
601
+
602
+ def error(str)
603
+ $stderr.puts str
604
+ exit(1)
605
+ end
606
+
607
+ end