Subversion Info

Rev
52
Last Checked In
2009-01-07 02:08:11 (4 years ago)
Checked in by
deveiant

Parent

Included Modules

RDoc::Generator::Darkfish

Darkfish RDoc HTML Generator

$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $

Author/s

Contributors

License

Copyright © 2007, 2008, Michael Granger. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Constants

SVNRev

Subversion rev

SVNId

Subversion ID

GENERATOR_DIR

Path to this file’s parent directory. Used to find templates and other resources.

VERSION

Release Version

CLASS_DIR

Directory where generated classes live relative to the root

FILE_DIR

Directory where generated files live relative to the root

SVNID_PATTERN

%q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $“

Attributes

outputdir[R]

The output directory

Public Class Methods

for( options ) click to toggle source

Standard generator factory method

    # File lib/rdoc/generator/darkfish.rb, line 84
84:         def self::for( options )
85:                 new( options )
86:         end
new( options ) click to toggle source

Initialize a few instance variables before we start

     # File lib/rdoc/generator/darkfish.rb, line 94
 94:         def initialize( options )
 95:                 @options = options
 96: 
 97:                 template = @options.template || 'darkfish'
 98: 
 99:                 template_dir = $LOAD_PATH.map do |path|
100:                         File.join File.expand_path(path), GENERATOR_DIR, 'template', template
101:                 end.find do |dir|
102:                         File.directory? dir
103:                 end
104: 
105:                 raise RDoc::Error, "could not find template #{template.inspect}" unless
106:                         template_dir
107: 
108:                 @template_dir = Pathname.new File.expand_path(template_dir)
109: 
110:                 @files      = nil
111:                 @classes    = nil
112: 
113:                 @basedir = Pathname.pwd.expand_path
114:         end

Public Instance Methods

class_dir() click to toggle source
     # File lib/rdoc/generator/darkfish.rb, line 130
130:         def class_dir
131:                 CLASS_DIR
132:         end
debug_msg( *msg ) click to toggle source

Output progress information if debugging is enabled

     # File lib/rdoc/generator/darkfish.rb, line 125
125:         def debug_msg( *msg )
126:                 return unless $DEBUG_RDOC
127:                 $stderr.puts( *msg )
128:         end
file_dir() click to toggle source
     # File lib/rdoc/generator/darkfish.rb, line 134
134:         def file_dir
135:                 FILE_DIR
136:         end
gen_sub_directories() click to toggle source

Create the directories the generated docs will live in if they don’t already exist.

     # File lib/rdoc/generator/darkfish.rb, line 140
140:         def gen_sub_directories
141:                 @outputdir.mkpath
142:         end
generate( top_levels ) click to toggle source

Build the initial indices and output objects based on an array of TopLevel objects containing the extracted information.

     # File lib/rdoc/generator/darkfish.rb, line 169
169:         def generate( top_levels )
170:                 @outputdir = Pathname.new( @options.op_dir ).expand_path( @basedir )
171: 
172:                 @files = top_levels.sort
173:                 @classes = RDoc::TopLevel.all_classes_and_modules.sort
174:                 @methods = @classes.map { |m| m.method_list }.flatten.sort
175:                 @modsort = get_sorted_module_list( @classes )
176: 
177:                 # Now actually write the output
178:                 write_style_sheet
179:                 generate_index
180:                 generate_class_files
181:                 generate_file_files
182: 
183:         rescue StandardError => err
184:                 debug_msg "%s: %s\n  %s" % [ err.class.name, err.message, err.backtrace.join("\n  ") ]
185:                 raise
186:         end
write_style_sheet() click to toggle source

Copy over the stylesheet into the appropriate place in the output directory.

     # File lib/rdoc/generator/darkfish.rb, line 146
146:         def write_style_sheet
147:                 debug_msg "Copying static files"
148:                 options = { :verbose => $DEBUG_RDOC, :noop => $DARKFISH_DRYRUN }
149: 
150:                 FileUtils.cp @template_dir + 'rdoc.css', '.', options
151: 
152:                 Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path|
153:                         next if File.directory? path
154:                         next if File.basename(path) =~ /^\./
155: 
156:                         dst = Pathname.new(path).relative_path_from @template_dir
157: 
158:                         # I suck at glob
159:                         dst_dir = dst.dirname
160:                         FileUtils.mkdir_p dst_dir, options unless File.exist? dst_dir
161: 
162:                         FileUtils.cp @template_dir + path, dst, options
163:                 end
164:         end

Protected Instance Methods

generate_class_files() click to toggle source

Generate a documentation file for each class

     # File lib/rdoc/generator/darkfish.rb, line 254
254:         def generate_class_files
255:                 template_file = @template_dir + 'classpage.rhtml'
256:                 return unless template_file.exist?
257:                 debug_msg "Generating class documentation in #@outputdir"
258: 
259:                 @classes.each do |klass|
260:                         debug_msg "  working on %s (%s)" % [ klass.full_name, klass.path ]
261:                         outfile    = @outputdir + klass.path
262:                         rel_prefix = @outputdir.relative_path_from( outfile.dirname )
263:                         svninfo    = self.get_svninfo( klass )
264: 
265:                         debug_msg "  rendering #{outfile}"
266:                         self.render_template( template_file, binding(), outfile )
267:                 end
268:         end
generate_file_files() click to toggle source

Generate a documentation file for each file

     # File lib/rdoc/generator/darkfish.rb, line 271
271:         def generate_file_files
272:                 template_file = @template_dir + 'filepage.rhtml'
273:                 return unless template_file.exist?
274:                 debug_msg "Generating file documentation in #@outputdir"
275: 
276:                 @files.each do |file|
277:                         outfile     = @outputdir + file.path
278:                         debug_msg "  working on %s (%s)" % [ file.full_name, outfile ]
279:                         rel_prefix  = @outputdir.relative_path_from( outfile.dirname )
280:                         context     = binding()
281: 
282:                         debug_msg "  rendering #{outfile}"
283:                         self.render_template( template_file, binding(), outfile )
284:                 end
285:         end
generate_index() click to toggle source

Generate an index page which lists all the classes which are documented.

     # File lib/rdoc/generator/darkfish.rb, line 219
219:         def generate_index
220:                 template_file = @template_dir + 'index.rhtml'
221:                 return unless template_file.exist?
222: 
223:                 debug_msg "Rendering the index page..."
224: 
225:                 template_src = template_file.read
226:                 template = ERB.new( template_src, nil, '<>' )
227:                 template.filename = template_file.to_s
228:                 context = binding()
229: 
230:                 output = nil
231: 
232:                 begin
233:                         output = template.result( context )
234:                 rescue NoMethodError => err
235:                         raise RDoc::Error, "Error while evaluating %s: %s (at %p)" % [
236:                                 template_file,
237:                                 err.message,
238:                                 eval( "_erbout[-50,50]", context )
239:                         ], err.backtrace
240:                 end
241: 
242:                 outfile = @basedir + @options.op_dir + 'index.html'
243:                 unless $DARKFISH_DRYRUN
244:                         debug_msg "Outputting to %s" % [outfile.expand_path]
245:                         outfile.open( 'w', 0644 ) do |fh|
246:                                 fh.print( output )
247:                         end
248:                 else
249:                         debug_msg "Would have output to %s" % [outfile.expand_path]
250:                 end
251:         end
get_sorted_module_list( classes ) click to toggle source

Return a list of the documented modules sorted by salience first, then by name.

     # File lib/rdoc/generator/darkfish.rb, line 194
194:         def get_sorted_module_list( classes )
195:                 nscounts = classes.inject({}) do |counthash, klass|
196:                         top_level = klass.full_name.gsub( /::.*/, '' )
197:                         counthash[top_level] ||= 0
198:                         counthash[top_level] += 1
199: 
200:                         counthash
201:                 end
202: 
203:                 # Sort based on how often the top level namespace occurs, and then on the
204:                 # name of the module -- this works for projects that put their stuff into
205:                 # a namespace, of course, but doesn't hurt if they don't.
206:                 classes.sort_by do |klass|
207:                         top_level = klass.full_name.gsub( /::.*/, '' )
208:                         [
209:                                 nscounts[ top_level ] * 1,
210:                                 klass.full_name
211:                         ]
212:                 end.select do |klass|
213:                         klass.document_self
214:                 end
215:         end
get_svninfo( klass ) click to toggle source

Try to extract Subversion information out of the first constant whose value looks like a subversion Id tag. If no matching constant is found, and empty hash is returned.

     # File lib/rdoc/generator/darkfish.rb, line 318
318:         def get_svninfo( klass )
319:                 constants = klass.constants or return {}
320: 
321:                 constants.find {|c| c.value =~ SVNID_PATTERN } or return {}
322: 
323:                 filename, rev, date, time, committer = $~.captures
324:                 commitdate = Time.parse( date + ' ' + time )
325: 
326:                 return {
327:                         :filename    => filename,
328:                         :rev         => Integer( rev ),
329:                         :commitdate  => commitdate,
330:                         :commitdelta => time_delta_string( Time.now.to_i - commitdate.to_i ),
331:                         :committer   => committer,
332:                 }
333:         end
render_template( template_file, context, outfile ) click to toggle source

Load and render the erb template in the given template_file within the specified context (a Binding object) and write it out to outfile. Both template_file and outfile should be Pathname-like objects.

     # File lib/rdoc/generator/darkfish.rb, line 340
340:         def render_template( template_file, context, outfile )
341:                 template_src = template_file.read
342:                 template = ERB.new( template_src, nil, '<>' )
343:                 template.filename = template_file.to_s
344: 
345:                 output = begin
346:                                                          template.result( context )
347:                                                  rescue NoMethodError => err
348:                                                          raise RDoc::Error, "Error while evaluating %s: %s (at %p)" % [
349:                                                                  template_file.to_s,
350:                                                                  err.message,
351:                                                                  eval( "_erbout[-50,50]", context )
352:                                                          ], err.backtrace
353:                                                  end
354: 
355:                 unless $DARKFISH_DRYRUN
356:                         outfile.dirname.mkpath
357:                         outfile.open( 'w', 0644 ) do |ofh|
358:                                 ofh.print( output )
359:                         end
360:                 else
361:                         debug_msg "  would have written %d bytes to %s" %
362:                         [ output.length, outfile ]
363:                 end
364:         end
time_delta_string( seconds ) click to toggle source

Return a string describing the amount of time in the given number of seconds in terms a human can understand easily.

     # File lib/rdoc/generator/darkfish.rb, line 290
290:         def time_delta_string( seconds )
291:                 return 'less than a minute' if seconds < 1.minute
292:                 return (seconds / 1.minute).to_s + ' minute' + (seconds/60 == 1 ? '' : 's') if seconds < 50.minutes
293:                 return 'about one hour' if seconds < 90.minutes
294:                 return (seconds / 1.hour).to_s + ' hours' if seconds < 18.hours
295:                 return 'one day' if seconds < 1.day
296:                 return 'about one day' if seconds < 2.days
297:                 return (seconds / 1.day).to_s + ' days' if seconds < 1.week
298:                 return 'about one week' if seconds < 2.week
299:                 return (seconds / 1.week).to_s + ' weeks' if seconds < 3.months
300:                 return (seconds / 1.month).to_s + ' months' if seconds < 1.year
301:                 return (seconds / 1.year).to_s + ' years'
302:         end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.