diff --git a/ChangeLog b/ChangeLog index bb105f291a..7129c64a8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Sat Nov 20 23:57:33 2004 Dave Thomas + + * lib/rdoc/README (et al): Add a new directive, :section:, and + change the output format to accomodate. :section: allows to to + group together methods, attributes, constants, etc under + headings in the output. If used, a table of contents is + generated. + +Sat Nov 20 23:56:54 2004 Dave Thomas + + * lib/rdoc/options.rb (Options::parse): Force --inline-source if + --one-file option given + Sat Nov 20 23:25:12 2004 Minero Aoki * io.c (rb_io_getline): f.gets("") did not work. [ruby-core:03771] diff --git a/lib/rdoc/README b/lib/rdoc/README index 5e90d792a2..583f7f3b0c 100644 --- a/lib/rdoc/README +++ b/lib/rdoc/README @@ -422,6 +422,13 @@ this margin are formatted verbatim. 12. Comment blocks can contain other directives: + [:section: title] + Starts a new section in the output. The title following + :section: is used as the section heading, and the + remainder of the comment containing the section is used as + introductory text. Subsequent methods, aliases, attributes, + and classes will be documented in this section. + [call-seq:] lines up to the next blank line in the comment are treated as the method's calling sequence, overriding the diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb index bd713ab92b..134ac398e9 100644 --- a/lib/rdoc/code_objects.rb +++ b/lib/rdoc/code_objects.rb @@ -23,6 +23,9 @@ module RDoc attr_accessor :done_documenting + # Which section are we in + + attr_accessor :section # do we document ourselves? @@ -111,7 +114,25 @@ module RDoc class Context < CodeObject attr_reader :name, :method_list, :attributes, :aliases, :constants attr_reader :requires, :includes, :in_files, :visibility - + + attr_reader :sections + + class Section + attr_reader :title, :comment, :sequence + + @@sequence = "SEC00000" + + def initialize(title, comment) + @title = title + @@sequence.succ! + @sequence = @@sequence.dup + if comment + @comment = comment.sub(/.*$/, '') + @comment = nil if @comment.empty? + end + end + end + def initialize super() @@ -123,6 +144,9 @@ module RDoc @parent = nil @visibility = :public + @current_section = Section.new(nil, nil) + @sections = [ @current_section ] + initialize_methods_etc initialize_classes_and_modules end @@ -236,6 +260,7 @@ module RDoc # collection[name] = cls if @document_self && !@done_documenting collection[name] = cls if !@done_documenting cls.parent = self + cls.section = @current_section end cls end @@ -243,6 +268,7 @@ module RDoc def add_to(array, thing) array << thing if @document_self && !@done_documenting thing.parent = self + thing.section = @current_section end # If a class's documentation is turned off after we've started @@ -374,6 +400,13 @@ module RDoc find_module_named(symbol) end + # Handle sections + + def set_current_section(title, comment) + @current_section = Section.new(title, comment) + @sections << @current_section + end + private # Find a named method, or return nil diff --git a/lib/rdoc/generators/html_generator.rb b/lib/rdoc/generators/html_generator.rb index fbfc596cc3..f9c72a4df2 100644 --- a/lib/rdoc/generators/html_generator.rb +++ b/lib/rdoc/generators/html_generator.rb @@ -336,8 +336,10 @@ module Generators # Build a list of aliases for which we couldn't find a # corresponding method - def build_alias_summary_list - @context.aliases.map do |al| + def build_alias_summary_list(section) + values = [] + @context.aliases.each do |al| + next unless al.section == section res = { 'old_name' => al.old_name, 'new_name' => al.new_name, @@ -345,20 +347,24 @@ module Generators if al.comment && !al.comment.empty? res['desc'] = markup(al.comment, true) end - res + values << res end + values end # Build a list of constants - def build_constants_summary_list - @context.constants.map do |co| + def build_constants_summary_list(section) + values = [] + @context.constants.each do |co| + next unless co.section == section res = { 'name' => co.name, 'value' => CGI.escapeHTML(co.value) } res['desc'] = markup(co.comment, true) if co.comment && !co.comment.empty? - res + values << res end + values end def build_requires_list(context) @@ -416,7 +422,7 @@ module Generators # methods, the other for instance methods. The inner arrays contain # a hash for each method - def build_method_detail_list + def build_method_detail_list(section) outer = [] methods = @methods.sort @@ -424,7 +430,10 @@ module Generators for vis in [ :public, :protected, :private ] res = [] methods.each do |m| - if m.document_self and m.visibility == vis and m.singleton == singleton + if m.section == section and + m.document_self and + m.visibility == vis and + m.singleton == singleton row = {} if m.call_seq row["callseq"] = m.call_seq.gsub(/->/, '→') @@ -478,11 +487,12 @@ module Generators # Build the structured list of classes and modules contained # in this context. - def build_class_list(level, from, infile=nil) + def build_class_list(level, from, section, infile=nil) res = "" prefix = "  ::" * level; from.modules.sort.each do |mod| + next unless mod.section == section next if infile && !mod.defined_in?(infile) if mod.document_self res << @@ -490,11 +500,12 @@ module Generators "Module " << href(url(mod.viewer.path), "link", mod.full_name) << "
\n" << - build_class_list(level + 1, mod, infile) + build_class_list(level + 1, mod, section, infile) end end from.classes.sort.each do |cls| + next unless cls.section == section next if infile && !cls.defined_in?(infile) if cls.document_self res << @@ -502,7 +513,7 @@ module Generators "Class " << href(url(cls.viewer.path), "link", cls.full_name) << "
\n" << - build_class_list(level + 1, cls, infile) + build_class_list(level + 1, cls, section, infile) end end @@ -541,6 +552,24 @@ module Generators end res end + + # create table of contents if we contain sections + + def add_table_of_sections + toc = [] + @context.sections.each do |section| + if section.title + toc << { + 'secname' => section.title, + 'href' => section.sequence + } + end + end + + @values['toc'] = toc unless toc.empty? + end + + end ##################################################################### @@ -604,6 +633,7 @@ module Generators def value_hash class_attribute_values + add_table_of_sections @values["charset"] = @options.charset @values["style_url"] = style_url(path, @options.css) @@ -614,30 +644,43 @@ module Generators ml = build_method_summary_list @values["methods"] = ml unless ml.empty? - al = build_alias_summary_list - @values["aliases"] = al unless al.empty? - - co = build_constants_summary_list - @values["constants"] = co unless co.empty? - il = build_include_list(@context) @values["includes"] = il unless il.empty? - al = build_attribute_list - @values["attributes"] = al unless al.empty? - - cl = build_class_list(0, @context) - @values["classlist"] = cl unless cl.empty? + @values["sections"] = @context.sections.map do |section| + + secdata = { + "sectitle" => section.title, + "secsequence" => section.sequence, + "seccomment" => markup(section.comment) + } + + al = build_alias_summary_list(section) + secdata["aliases"] = al unless al.empty? + + co = build_constants_summary_list(section) + secdata["constants"] = co unless co.empty? + + al = build_attribute_list(section) + secdata["attributes"] = al unless al.empty? + + cl = build_class_list(0, @context, section) + secdata["classlist"] = cl unless cl.empty? + + mdl = build_method_detail_list(section) + secdata["method_list"] = mdl unless mdl.empty? + + secdata + end - mdl = build_method_detail_list - @values["method_list"] = mdl unless mdl.empty? @values end - def build_attribute_list + def build_attribute_list(section) atts = @context.attributes.sort res = [] atts.each do |att| + next unless att.section == section if att.visibility == :public || @options.show_all entry = { "name" => CGI.escapeHTML(att.name), @@ -701,7 +744,6 @@ module Generators end @values['infiles'] = files - end def <=>(other) @@ -759,6 +801,7 @@ module Generators def value_hash file_attribute_values + add_table_of_sections @values["charset"] = @options.charset @values["href"] = path @@ -778,23 +821,36 @@ module Generators rl = build_requires_list(@context) @values["requires"] = rl unless rl.empty? - co = build_constants_summary_list - @values["constants"] = co unless co.empty? - - al = build_alias_summary_list - @values["aliases"] = al unless al.empty? - if @options.promiscuous file_context = nil else file_context = @context end - cl = build_class_list(0, @context, file_context) - @values["classlist"] = cl unless cl.empty? - mdl = build_method_detail_list - @values["method_list"] = mdl unless mdl.empty? + @values["sections"] = @context.sections.map do |section| + + secdata = { + "sectitle" => section.title, + "secsequence" => section.sequence, + "seccomment" => markup(section.comment) + } + + cl = build_class_list(0, @context, section, file_context) + @values["classlist"] = cl unless cl.empty? + + mdl = build_method_detail_list(section) + secdata["method_list"] = mdl unless mdl.empty? + + al = build_alias_summary_list(section) + secdata["aliases"] = al unless al.empty? + + co = build_constants_summary_list(section) + @values["constants"] = co unless co.empty? + + secdata + end + @values end @@ -885,6 +941,10 @@ module Generators @context.name end + def section + @context.section + end + def index_name "#{@context.name} (#{@html_class.name})" end diff --git a/lib/rdoc/generators/template/html/html.rb b/lib/rdoc/generators/template/html/html.rb index e0a8880004..fd9917b43a 100644 --- a/lib/rdoc/generators/template/html/html.rb +++ b/lib/rdoc/generators/template/html/html.rb @@ -20,19 +20,22 @@ # module RDoc - module Page + module Page - FONTS = "Verdana,Arial,Helvetica,sans-serif" + FONTS = "Verdana,Arial,Helvetica,sans-serif" STYLE = %{ body { + font-family: Verdana,Arial,Helvetica,sans-serif; + font-size: 90%; margin: 0; + margin-left: 40px; padding: 0; background: white; } h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } -h1 { font-size: 120%; } +h1 { font-size: 150%; } h2,h3,h4 { margin-top: 1em; } a { background: #eef; color: #039; text-decoration: none; } @@ -40,61 +43,75 @@ a:hover { background: #039; color: #eef; } /* Override the base stylesheet's Anchor inside a table cell */ td > a { - background: transparent; - color: #039; - text-decoration: none; + background: transparent; + color: #039; + text-decoration: none; +} + +/* and inside a section title */ +.section-title > a { + background: transparent; + color: #eee; + text-decoration: none; } /* === Structural elements =================================== */ div#index { margin: 0; + margin-left: -40px; padding: 0; - font-size: 0.9em; + font-size: 90%; } + div#index a { margin-left: 0.7em; } -div#classHeader { +div#index .section-bar { + margin-left: 0px; + padding-left: 0.7em; + background: #ccc; + font-size: small; +} + + +div#classHeader, div#fileHeader { width: auto; - background: #039; color: white; padding: 0.5em 1.5em 0.5em 1.5em; margin: 0; + margin-left: -40px; border-bottom: 3px solid #006; } -div#classHeader a { +div#classHeader a, div#fileHeader a { background: inherit; color: white; } -div#classHeader td { +div#classHeader td, div#fileHeader td { background: inherit; color: white; } + div#fileHeader { - width: auto; - background: #039; - color: white; - padding: 0.5em 1.5em 0.5em 1.5em; - margin: 0; - border-bottom: 3px solid #006; + background: #057; } -div#fileHeader a { - background: inherit; - color: white; +div#classHeader { + background: #048; } -div#fileHeader td { - background: inherit; - color: white; + +.class-name-in-header { + font-size: 180%; + font-weight: bold; } + div#bodyContent { padding: 0 1.5em 0 1.5em; } @@ -105,7 +122,7 @@ div#description { border: 1px dotted #999; } -div#description h1,h2,h3,h4,h5,h6 { +div#description h1,h3,h3,h4,h5,h6 { color: black; background: transparent; } @@ -137,35 +154,51 @@ table.header-table { color: #DEDEDE; } -.section-bar { +.xxsection-bar { background: #eee; color: #333; padding: 3px; +} + +.section-bar { + color: #333; + border-bottom: 1px solid #999; + margin-left: -20px; +} + + +.section-title { + background: #79a; + color: #eee; + padding: 3px; + margin-top: 2em; + margin-left: -30px; border: 1px solid #999; } -.top-aligned-row { vertical-align: vertical-align: top } +.top-aligned-row { vertical-align: top } +.bottom-aligned-row { vertical-align: bottom } /* --- Context section classes ----------------------- */ .context-row { } .context-item-name { font-family: monospace; font-weight: bold; color: black; } -.context-item-value { font-size: x-small; color: #448; } -.context-item-desc { background: #efefef; } +.context-item-value { font-size: small; color: #448; } +.context-item-desc { color: #333; padding-left: 2em; } /* --- Method classes -------------------------- */ .method-detail { - background: #EFEFEF; + background: #efefef; padding: 0; margin-top: 0.5em; - margin-bottom: 0.5em; - border: 1px dotted #DDD; + margin-bottom: 1em; + border: 1px dotted #ccc; } .method-heading { - color: black; - background: #AAA; - border-bottom: 1px solid #666; - padding: 0.2em 0.5em 0 0.5em; + color: black; + background: #ccc; + border-bottom: 1px solid #666; + padding: 0.2em 0.5em 0 0.5em; } .method-signature { color: black; background: inherit; } .method-name { font-weight: bold; } @@ -178,7 +211,7 @@ a.source-toggle { font-size: 90%; } div.method-source-code { background: #262626; color: #ffdead; - margin: 1em; + margin: 1em; padding: 0.5em; border: 1px dashed #999; overflow: hidden; @@ -190,20 +223,20 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; } .standalone-code { background: #221111; color: #ffdead; overflow: hidden; } -.ruby-constant { color: #7fffd4; background: transparent; } -.ruby-keyword { color: #00ffff; background: transparent; } -.ruby-ivar { color: #eedd82; background: transparent; } -.ruby-operator { color: #00ffee; background: transparent; } +.ruby-constant { color: #7fffd4; background: transparent; } +.ruby-keyword { color: #00ffff; background: transparent; } +.ruby-ivar { color: #eedd82; background: transparent; } +.ruby-operator { color: #00ffee; background: transparent; } .ruby-identifier { color: #ffdead; background: transparent; } -.ruby-node { color: #ffa07a; background: transparent; } -.ruby-comment { color: #b22222; font-weight: bold; background: transparent; } -.ruby-regexp { color: #ffa07a; background: transparent; } -.ruby-value { color: #7fffd4; background: transparent; } +.ruby-node { color: #ffa07a; background: transparent; } +.ruby-comment { color: #b22222; font-weight: bold; background: transparent; } +.ruby-regexp { color: #ffa07a; background: transparent; } +.ruby-value { color: #7fffd4; background: transparent; } } ##################################################################### -### H E A D E R T E M P L A T E +### H E A D E R T E M P L A T E ##################################################################### XHTML_PREAMBLE = %{ @@ -215,41 +248,41 @@ XHTML_PREAMBLE = %{ HEADER = XHTML_PREAMBLE + %{ - %title% - - - - + return true; + } + + // Make codeblocks hidden by default + document.writeln( "" ) + + // ]]> + @@ -257,129 +290,15 @@ HEADER = XHTML_PREAMBLE + %{ ##################################################################### -### C O N T E X T C O N T E N T T E M P L A T E +### C O N T E X T C O N T E N T T E M P L A T E ##################################################################### CONTEXT_CONTENT = %{ -
-IF:diagram -
- %diagram% -
-ENDIF:diagram - -IF:description -
- %description% -
-ENDIF:description - -IF:requires -
-

Required files

- -
-START:requires - HREF:aref:name:   -END:requires -
-
-ENDIF:requires - -IF:methods -
-

Methods

- -
-START:methods - HREF:aref:name:   -END:methods -
-
-ENDIF:methods - -IF:constants -
-

Constants

- -
- -START:constants - - - - - -IF:desc - - - - -ENDIF:desc -END:constants -
%name%=%value%
 %desc%
-
-
-ENDIF:constants - -IF:aliases -
-

External Aliases

- -
- -START:aliases - - - - - -IF:desc - - - - -ENDIF:desc -END:aliases -
%old_name%->%new_name%
 %desc%
-
-
-ENDIF:aliases - - -IF:attributes -
-

Attributes

- -
- -START:attributes - - - - - -END:attributes -
%name% [%rw%] %a_desc%
-
-
-ENDIF:attributes - -IF:classlist -
-

Classes and Modules

- - %classlist% -
-ENDIF:classlist - -
- } ##################################################################### -### F O O T E R T E M P L A T E +### F O O T E R T E M P L A T E ##################################################################### FOOTER = %{
@@ -392,38 +311,41 @@ FOOTER = %{ ##################################################################### -### F I L E P A G E H E A D E R T E M P L A T E +### F I L E P A G E H E A D E R T E M P L A T E ##################################################################### FILE_PAGE = %{ -
-

%short_name%

- - - - + + + + + +
Path:%full_path% +
+

%short_name%

+ + + + - - - - - -
Path:%full_path% IF:cvsurl -  (CVS) +  (CVS) ENDIF:cvsurl -
Last Update:%dtm_modified%
-
+
Last Update:%dtm_modified%
+
} ##################################################################### -### C L A S S P A G E H E A D E R T E M P L A T E +### C L A S S P A G E H E A D E R T E M P L A T E ##################################################################### CLASS_PAGE = %{
-

%full_name% (%classmod%)

+ + + + @@ -463,121 +385,258 @@ ENDIF:parent ##################################################################### -### M E T H O D L I S T T E M P L A T E +### M E T H O D L I S T T E M P L A T E ##################################################################### METHOD_LIST = %{ - -IF:includes -
-

Included Modules

+
+IF:diagram +
+ %diagram% +
+ENDIF:diagram -
+IF:description +
+ %description% +
+ENDIF:description + +IF:requires +
+

Required files

+ +
+START:requires + HREF:aref:name:   +END:requires +
+
+ENDIF:requires + +IF:toc +
+

Contents

+ +ENDIF:toc +
+ +IF:methods +
+

Methods

+ +
+START:methods + HREF:aref:name:   +END:methods +
+
+ENDIF:methods + +
+ + + +IF:includes +
+

Included Modules

+ +
START:includes - HREF:aref:name: + HREF:aref:name: END:includes -
-
+
+
ENDIF:includes +START:sections +
+IF:sectitle +

%sectitle%

+IF:seccomment +
+ %seccomment% +
+ENDIF:seccomment +ENDIF:sectitle - +IF:classlist +
+

Classes and Modules

+ + %classlist% +
+ENDIF:classlist + +IF:constants +
+

Constants

+ +
+
%classmod%%full_name%
In: @@ -436,9 +358,9 @@ IF:full_path_url ENDIF:full_path_url IF:cvsurl -  (CVS) +  (CVS) ENDIF:cvsurl -
+
END:infiles
+START:constants + + + + +IF:desc + + +ENDIF:desc + +END:constants +
%name%=%value% %desc%
+
+
+ENDIF:constants + +IF:aliases +
+

External Aliases

+ +
+ +START:aliases + + + + + +IF:desc + + + + +ENDIF:desc +END:aliases +
%old_name%->%new_name%
 %desc%
+
+
+ENDIF:aliases + + +IF:attributes +
+

Attributes

+ +
+ +START:attributes + + + + + +END:attributes +
%name% [%rw%] %a_desc%
+
+
+ENDIF:attributes + + + + IF:method_list -
+
START:method_list IF:methods -

%type% %category% methods

+

%type% %category% methods

START:methods -
- +
+ -
+ - -
+
+ +
IF:m_desc - %m_desc% + %m_desc% ENDIF:m_desc IF:sourcecode -

[Source]

-
+

[Source]

+
 %sourcecode%
 
-
+
ENDIF:sourcecode -
-
+
+
END:methods ENDIF:methods END:method_list -
+
ENDIF:method_list +END:sections } ##################################################################### -### B O D Y T E M P L A T E +### B O D Y T E M P L A T E ##################################################################### BODY = HEADER + %{ !INCLUDE! -
+
-} + CONTEXT_CONTENT + METHOD_LIST + %{ +} + METHOD_LIST + %{ -
+
} + FOOTER ##################################################################### -### S O U R C E C O D E T E M P L A T E +### S O U R C E C O D E T E M P L A T E ##################################################################### SRC_PAGE = XHTML_PREAMBLE + %{ - %title% - - + %title% + + -
%code%
+
%code%
} ##################################################################### -### I N D E X F I L E T E M P L A T E S +### I N D E X F I L E T E M P L A T E S ##################################################################### FR_INDEX_BODY = %{ @@ -592,19 +651,19 @@ FILE_INDEX = XHTML_PREAMBLE + %{ --> - %list_title% - - - + %list_title% + + +
-

%list_title%

-
+

%list_title%

+
START:entries - %name%
+ %name%
END:entries -
+
@@ -625,8 +684,8 @@ INDEX = %{ --> - %title% - + %title% + @@ -641,7 +700,7 @@ INDEX = %{ - end # module Page + end # module Page end # class RDoc require 'rdoc/generators/template/html/one_page_html' diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb index 62c6dabff0..53eee992e2 100644 --- a/lib/rdoc/options.rb +++ b/lib/rdoc/options.rb @@ -391,7 +391,7 @@ class Options when "--line-numbers" then @include_line_numbers = true when "--main" then @main_page = arg when "--merge" then @merge = true - when "--one-file" then @all_one_file = true + when "--one-file" then @all_one_file = @inline_source = true when "--op" then @op_dir = arg when "--opname" then @op_name = arg when "--promiscuous" then @promiscuous = true diff --git a/lib/rdoc/parsers/parse_rb.rb b/lib/rdoc/parsers/parse_rb.rb index b8367b5641..8f1206409a 100644 --- a/lib/rdoc/parsers/parse_rb.rb +++ b/lib/rdoc/parsers/parse_rb.rb @@ -1580,23 +1580,6 @@ module RDoc non_comment_seen = true unless tk.kind_of?(TkCOMMENT) -# $stderr.puts "===== #{tk.inspect}" -# blank_line_seen = true -# while tk.kind_of?(TkNL) -# skip_tkspace(false) -# if peek_tk.kind_of?(TkCOMMENT) -# if blank_line_seen -# comment = '' -# blank_line_seen = false -# end -# tk = get_tk -# comment << tk.text << "\n" -# else -# blank_line_seen = true -# end -# tk = get_tk -# end - case tk when TkNL @@ -2326,6 +2309,10 @@ module RDoc options.title = param "" + when "section" + context.set_current_section(param, comment) + comment.clear + "" else warn "Unrecognized directive '#{directive}'" break @@ -2548,7 +2535,7 @@ module RDoc break when TkCOMMA else - warn("unexpected token: '#{tk.inspect}'") + warn("unexpected token: '#{tk2.inspect}'") if $DEBBUG break end end