sqlpostgres 1.2.4

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.
Files changed (207) hide show
  1. data/Gemfile +8 -0
  2. data/Gemfile.lock +22 -0
  3. data/LICENSE.md +23 -0
  4. data/README.rdoc +59 -0
  5. data/Rakefile +32 -0
  6. data/VERSION +1 -0
  7. data/doc/BUGS +2 -0
  8. data/doc/examples/README +6 -0
  9. data/doc/examples/connection.rb +16 -0
  10. data/doc/examples/connection_auto.rb +22 -0
  11. data/doc/examples/connection_ctor.rb +18 -0
  12. data/doc/examples/connection_default.rb +15 -0
  13. data/doc/examples/connection_exec.rb +18 -0
  14. data/doc/examples/connection_manual.rb +12 -0
  15. data/doc/examples/connection_wrapped_new.rb +13 -0
  16. data/doc/examples/connection_wrapped_open.rb +13 -0
  17. data/doc/examples/cursor.rb +38 -0
  18. data/doc/examples/include_module.rb +9 -0
  19. data/doc/examples/include_module2.rb +12 -0
  20. data/doc/examples/insert.rb +30 -0
  21. data/doc/examples/insert2.rb +36 -0
  22. data/doc/examples/insert_bytea.rb +16 -0
  23. data/doc/examples/insert_bytea_array.rb +17 -0
  24. data/doc/examples/insert_default_values.rb +16 -0
  25. data/doc/examples/insert_insert.rb +16 -0
  26. data/doc/examples/insert_insert_default.rb +16 -0
  27. data/doc/examples/insert_insert_select.rb +20 -0
  28. data/doc/examples/insert_select.rb +20 -0
  29. data/doc/examples/interval.rb +17 -0
  30. data/doc/examples/savepoint.rb +38 -0
  31. data/doc/examples/select.rb +33 -0
  32. data/doc/examples/select2.rb +36 -0
  33. data/doc/examples/select_cross_join.rb +18 -0
  34. data/doc/examples/select_distinct.rb +18 -0
  35. data/doc/examples/select_distinct_on +19 -0
  36. data/doc/examples/select_for_update.rb +18 -0
  37. data/doc/examples/select_from.rb +17 -0
  38. data/doc/examples/select_from_subselect.rb +20 -0
  39. data/doc/examples/select_group_by.rb +19 -0
  40. data/doc/examples/select_having.rb +20 -0
  41. data/doc/examples/select_join_on.rb +18 -0
  42. data/doc/examples/select_join_using.rb +18 -0
  43. data/doc/examples/select_limit.rb +19 -0
  44. data/doc/examples/select_natural_join.rb +18 -0
  45. data/doc/examples/select_offset.rb +19 -0
  46. data/doc/examples/select_order_by.rb +20 -0
  47. data/doc/examples/select_select.rb +30 -0
  48. data/doc/examples/select_select_alias.rb +30 -0
  49. data/doc/examples/select_select_expression.rb +31 -0
  50. data/doc/examples/select_select_literal.rb +24 -0
  51. data/doc/examples/select_union.rb +21 -0
  52. data/doc/examples/select_where_array.rb +18 -0
  53. data/doc/examples/select_where_in.rb +18 -0
  54. data/doc/examples/select_where_string.rb +18 -0
  55. data/doc/examples/simple.rb +34 -0
  56. data/doc/examples/transaction.rb +30 -0
  57. data/doc/examples/transaction_abort.rb +30 -0
  58. data/doc/examples/transaction_commit.rb +34 -0
  59. data/doc/examples/translate_substitute_values.rb +17 -0
  60. data/doc/examples/update.rb +32 -0
  61. data/doc/examples/update2.rb +44 -0
  62. data/doc/examples/update_only.rb +17 -0
  63. data/doc/examples/update_set.rb +17 -0
  64. data/doc/examples/update_set_array.rb +16 -0
  65. data/doc/examples/update_set_bytea.rb +16 -0
  66. data/doc/examples/update_set_expression.rb +16 -0
  67. data/doc/examples/update_set_subselect.rb +20 -0
  68. data/doc/examples/update_where.rb +17 -0
  69. data/doc/examples/use_prefix.rb +8 -0
  70. data/doc/examples/use_prefix2.rb +11 -0
  71. data/doc/index.html +31 -0
  72. data/doc/insertexamples.rb +9 -0
  73. data/doc/makemanual +4 -0
  74. data/doc/makerdoc +5 -0
  75. data/doc/manual.dbk +622 -0
  76. data/lib/sqlpostgres/Connection.rb +198 -0
  77. data/lib/sqlpostgres/Cursor.rb +157 -0
  78. data/lib/sqlpostgres/Delete.rb +67 -0
  79. data/lib/sqlpostgres/Exceptions.rb +15 -0
  80. data/lib/sqlpostgres/Insert.rb +279 -0
  81. data/lib/sqlpostgres/NullConnection.rb +22 -0
  82. data/lib/sqlpostgres/PgBit.rb +73 -0
  83. data/lib/sqlpostgres/PgBox.rb +37 -0
  84. data/lib/sqlpostgres/PgCidr.rb +21 -0
  85. data/lib/sqlpostgres/PgCircle.rb +75 -0
  86. data/lib/sqlpostgres/PgInet.rb +21 -0
  87. data/lib/sqlpostgres/PgInterval.rb +208 -0
  88. data/lib/sqlpostgres/PgLineSegment.rb +37 -0
  89. data/lib/sqlpostgres/PgMacAddr.rb +21 -0
  90. data/lib/sqlpostgres/PgPath.rb +64 -0
  91. data/lib/sqlpostgres/PgPoint.rb +65 -0
  92. data/lib/sqlpostgres/PgPolygon.rb +56 -0
  93. data/lib/sqlpostgres/PgTime.rb +77 -0
  94. data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
  95. data/lib/sqlpostgres/PgTimestamp.rb +93 -0
  96. data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
  97. data/lib/sqlpostgres/PgType.rb +34 -0
  98. data/lib/sqlpostgres/PgWrapper.rb +41 -0
  99. data/lib/sqlpostgres/Savepoint.rb +98 -0
  100. data/lib/sqlpostgres/Select.rb +855 -0
  101. data/lib/sqlpostgres/Transaction.rb +120 -0
  102. data/lib/sqlpostgres/Translate.rb +436 -0
  103. data/lib/sqlpostgres/Update.rb +188 -0
  104. data/lib/sqlpostgres.rb +67 -0
  105. data/test/Assert.rb +72 -0
  106. data/test/Connection.test.rb +246 -0
  107. data/test/Cursor.test.rb +190 -0
  108. data/test/Delete.test.rb +68 -0
  109. data/test/Insert.test.rb +123 -0
  110. data/test/MockPGconn.rb +62 -0
  111. data/test/NullConnection.test.rb +32 -0
  112. data/test/PgBit.test.rb +98 -0
  113. data/test/PgBox.test.rb +108 -0
  114. data/test/PgCidr.test.rb +61 -0
  115. data/test/PgCircle.test.rb +107 -0
  116. data/test/PgInet.test.rb +61 -0
  117. data/test/PgInterval.test.rb +180 -0
  118. data/test/PgLineSegment.test.rb +108 -0
  119. data/test/PgMacAddr.test.rb +61 -0
  120. data/test/PgPath.test.rb +106 -0
  121. data/test/PgPoint.test.rb +100 -0
  122. data/test/PgPolygon.test.rb +95 -0
  123. data/test/PgTime.test.rb +120 -0
  124. data/test/PgTimeWithTimeZone.test.rb +117 -0
  125. data/test/PgTimestamp.test.rb +134 -0
  126. data/test/RandomThings.rb +25 -0
  127. data/test/Savepoint.test.rb +286 -0
  128. data/test/Select.test.rb +930 -0
  129. data/test/Test.rb +62 -0
  130. data/test/TestConfig.rb +21 -0
  131. data/test/TestSetup.rb +13 -0
  132. data/test/TestUtil.rb +92 -0
  133. data/test/Transaction.test.rb +275 -0
  134. data/test/Translate.test.rb +354 -0
  135. data/test/Update.test.rb +227 -0
  136. data/test/roundtrip.test.rb +565 -0
  137. data/test/test +34 -0
  138. data/tools/exampleinserter/ExampleInserter.rb +177 -0
  139. data/tools/rdoc/ChangeLog +796 -0
  140. data/tools/rdoc/EXAMPLE.rb +48 -0
  141. data/tools/rdoc/MANIFEST +58 -0
  142. data/tools/rdoc/Makefile +27 -0
  143. data/tools/rdoc/NEW_FEATURES +226 -0
  144. data/tools/rdoc/README +390 -0
  145. data/tools/rdoc/ToDo +6 -0
  146. data/tools/rdoc/contrib/Index +6 -0
  147. data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
  148. data/tools/rdoc/contrib/xslfo/README +106 -0
  149. data/tools/rdoc/contrib/xslfo/TODO +10 -0
  150. data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
  151. data/tools/rdoc/contrib/xslfo/demo/README +21 -0
  152. data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
  153. data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
  154. data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
  155. data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
  156. data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
  157. data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
  158. data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
  159. data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
  160. data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
  161. data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
  162. data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
  163. data/tools/rdoc/debian/changelog +33 -0
  164. data/tools/rdoc/debian/compat +1 -0
  165. data/tools/rdoc/debian/control +20 -0
  166. data/tools/rdoc/debian/copyright +10 -0
  167. data/tools/rdoc/debian/dirs +2 -0
  168. data/tools/rdoc/debian/docs +2 -0
  169. data/tools/rdoc/debian/rdoc.1 +252 -0
  170. data/tools/rdoc/debian/rdoc.manpages +1 -0
  171. data/tools/rdoc/debian/rdoc.pod +149 -0
  172. data/tools/rdoc/debian/rules +9 -0
  173. data/tools/rdoc/dot/dot.rb +255 -0
  174. data/tools/rdoc/etc/rdoc.dtd +203 -0
  175. data/tools/rdoc/install.rb +137 -0
  176. data/tools/rdoc/markup/install.rb +43 -0
  177. data/tools/rdoc/markup/sample/sample.rb +42 -0
  178. data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
  179. data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
  180. data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
  181. data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
  182. data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
  183. data/tools/rdoc/markup/simple_markup.rb +474 -0
  184. data/tools/rdoc/markup/test/AllTests.rb +2 -0
  185. data/tools/rdoc/markup/test/TestInline.rb +151 -0
  186. data/tools/rdoc/markup/test/TestParse.rb +411 -0
  187. data/tools/rdoc/rdoc/code_objects.rb +536 -0
  188. data/tools/rdoc/rdoc/diagram.rb +331 -0
  189. data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
  190. data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
  191. data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
  192. data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
  193. data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
  194. data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
  195. data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
  196. data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
  197. data/tools/rdoc/rdoc/options.rb +451 -0
  198. data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
  199. data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
  200. data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
  201. data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
  202. data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
  203. data/tools/rdoc/rdoc/rdoc.rb +219 -0
  204. data/tools/rdoc/rdoc/template.rb +234 -0
  205. data/tools/rdoc/rdoc/tokenstream.rb +25 -0
  206. data/tools/rdoc/rdoc.rb +9 -0
  207. metadata +291 -0
@@ -0,0 +1,1268 @@
1
+ # We're responsible for generating all the HTML files
2
+ # from the object tree defined in code_objects.rb. We
3
+ # generate:
4
+ #
5
+ # [files] an html file for each input file given. These
6
+ # input files appear as objects of class
7
+ # TopLevel
8
+ #
9
+ # [classes] an html file for each class or module encountered.
10
+ # These classes are not grouped by file: if a file
11
+ # contains four classes, we'll generate an html
12
+ # file for the file itself, and four html files
13
+ # for the individual classes.
14
+ #
15
+ # [indices] we generate three indices for files, classes,
16
+ # and methods. These are displayed in a browser
17
+ # like window with three index panes across the
18
+ # top and the selected description below
19
+ #
20
+ # Method descriptions appear in whatever entity (file, class,
21
+ # or module) that contains them.
22
+ #
23
+ # We generate files in a structure below a specified subdirectory,
24
+ # normally +doc+.
25
+ #
26
+ # opdir
27
+ # |
28
+ # |___ files
29
+ # | |__ per file summaries
30
+ # |
31
+ # |___ classes
32
+ # |__ per class/module descriptions
33
+ #
34
+ # HTML is generated using the Template class.
35
+ #
36
+
37
+ require 'ftools'
38
+
39
+ require 'rdoc/options'
40
+ require 'rdoc/template'
41
+ require 'markup/simple_markup'
42
+ require 'markup/simple_markup/to_html'
43
+ require 'cgi'
44
+
45
+ module Generators
46
+
47
+ # Name of sub-direcories that hold file and class/module descriptions
48
+
49
+ FILE_DIR = "files"
50
+ CLASS_DIR = "classes"
51
+ CSS_NAME = "rdoc-style.css"
52
+
53
+
54
+ ##
55
+ # Build a hash of all items that can be cross-referenced.
56
+ # This is used when we output required and included names:
57
+ # if the names appear in this hash, we can generate
58
+ # an html cross reference to the appropriate description.
59
+ # We also use this when parsing comment blocks: any decorated
60
+ # words matching an entry in this list are hyperlinked.
61
+
62
+ class AllReferences
63
+ @@refs = {}
64
+
65
+ def AllReferences::reset
66
+ @@refs = {}
67
+ end
68
+
69
+ def AllReferences.add(name, html_class)
70
+ @@refs[name] = html_class
71
+ end
72
+
73
+ def AllReferences.[](name)
74
+ @@refs[name]
75
+ end
76
+ end
77
+
78
+
79
+ ##
80
+ # Subclass of the SM::ToHtml class that supports looking
81
+ # up words in the AllReferences list. Those that are
82
+ # found (like AllReferences in this comment) will
83
+ # be hyperlinked
84
+
85
+ class HyperlinkHtml < SM::ToHtml
86
+ # We need to record the html path of our caller so we can generate
87
+ # correct relative paths for any hyperlinks that we find
88
+ def initialize(from_path, context)
89
+ super()
90
+ @from_path = from_path
91
+
92
+ @parent_name = context.parent_name
93
+ @parent_name += "::" if @parent_name
94
+ end
95
+
96
+ # We're invoked when any text matches the CROSSREF pattern
97
+ # (defined in MarkUp). If we fine the corresponding reference,
98
+ # generate a hyperlink. If the name we're looking for contains
99
+ # no punctuation, we look for it up the module/class chain. For
100
+ # example, HyperlinkHtml is found, even without the Generators::
101
+ # prefix, because we look for it in module Generators first.
102
+
103
+ def handle_special_CROSSREF(special)
104
+ name = special.text
105
+ if name[0,1] == '#'
106
+ lookup = name[1..-1]
107
+ name = lookup unless Options.instance.show_hash
108
+ else
109
+ lookup = name
110
+ end
111
+
112
+ ref = nil
113
+
114
+ if @parent_name and lookup !~ /\.:/
115
+ ref = AllReferences[@parent_name + lookup]
116
+ end
117
+
118
+ if !ref
119
+ ref = AllReferences[lookup]
120
+ end
121
+
122
+ if ref and ref.document_self
123
+ "<a href=\"#{ref.as_href(@from_path)}\">#{name}</a>"
124
+ else
125
+ name
126
+ end
127
+ end
128
+
129
+ # And we're invoked with a potential external hyperlink mailto:
130
+ # just gets inserted. http: links are checked to see if they
131
+ # reference an image. If so, that image gets inserted using an
132
+ # <img> tag. Otherwise a conventional <a href> is used. We also
133
+ # support a special type of hyperlink, link:, which is a reference
134
+ # to a local file whose path is relative to the --op directory.
135
+
136
+ def handle_special_HYPERLINK(special)
137
+ url = special.text
138
+ if url =~ /([A-Za-z]+):(.*)/
139
+ type = $1
140
+ path = $2
141
+ else
142
+ type = "http"
143
+ path = url
144
+ url = "http://#{url}"
145
+ end
146
+
147
+ if type == "link"
148
+ if path[0,1] == '#' # is this meaningful?
149
+ url = path
150
+ else
151
+ url = HTMLGenerator.gen_url(@from_path, path)
152
+ end
153
+ end
154
+
155
+ if (type == "http" || type == "link") &&
156
+ url =~ /\.(gif|png|jpg|jpeg|bmp)$/
157
+
158
+ "<img src=\"#{url}\">"
159
+ else
160
+ "<a href=\"#{url}\">#{url.sub(%r{^\w+:/*}, '')}</a>"
161
+ end
162
+ end
163
+
164
+ # HEre's a hypedlink where the label is different to the URL
165
+ # <label>[url]
166
+ #
167
+
168
+ def handle_special_TIDYLINK(special)
169
+ text = special.text
170
+ unless text =~ /(\S+)\[(.*?)\]/
171
+ return text
172
+ end
173
+ label = $1
174
+ url = $2
175
+
176
+ unless url =~ /\w+?:/
177
+ url = "http://#{url}"
178
+ end
179
+
180
+ "<a href=\"#{url}\">#{label}</a>"
181
+ end
182
+
183
+ end
184
+
185
+
186
+
187
+ #####################################################################
188
+ #
189
+ # Handle common markup tasks for the various Html classes
190
+ #
191
+
192
+ module MarkUp
193
+
194
+ # Convert a string in markup format into HTML. We keep a cached
195
+ # SimpleMarkup object lying around after the first time we're
196
+ # called per object.
197
+
198
+ def markup(str)
199
+ return '' unless str
200
+ unless defined? @markup
201
+ @markup = SM::SimpleMarkup.new
202
+
203
+ # class names, variable names, file names, or instance variables
204
+ @markup.add_special(/(
205
+ \b([A-Z]\w+(::\w+)*)
206
+ | \#\w+[!?=]?
207
+ | \b\w+([_\/\.]+\w+)+[!?=]?
208
+ )/x,
209
+ :CROSSREF)
210
+
211
+ # external hyperlinks
212
+ @markup.add_special(/((link:|http:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
213
+
214
+ # and links of the form <text>[<url>]
215
+ @markup.add_special(/\b(\S+?\[\S+?\.\S+?\])/, :TIDYLINK)
216
+
217
+ end
218
+ unless defined? @html_formatter
219
+ @html_formatter = HyperlinkHtml.new(self.path, self)
220
+ end
221
+
222
+ # Convert leading comment markers to spaces, but only
223
+ # if all non-blank lines have them
224
+
225
+ if str =~ /^(?>\s*)[^\#]/
226
+ content = str
227
+ else
228
+ content = str.gsub(/^\s*(#+)/) { $1.tr('#',' ') }
229
+ end
230
+
231
+ @markup.convert(content, @html_formatter)
232
+ end
233
+ end
234
+
235
+
236
+ #####################################################################
237
+ #
238
+ # A Context is built by the parser to represent a container: contexts
239
+ # hold classes, modules, methods, require lists and include lists.
240
+ # ClassModule and TopLevel are the context objects we process here
241
+ #
242
+ class ContextUser
243
+
244
+ include MarkUp
245
+
246
+ attr_reader :context
247
+
248
+ def initialize(context, options)
249
+ @context = context
250
+ @options = options
251
+ end
252
+
253
+ # convenience method to build a hyperlink
254
+ def href(link, cls, name)
255
+ %{<a href="#{link}" class="#{cls}">#{name}</a>} #"
256
+ end
257
+
258
+ # return a reference to outselves to be used as an href=
259
+ # the form depends on whether we're all in one file
260
+ # or in multiple files
261
+
262
+ def as_href(from_path)
263
+ if @options.all_one_file
264
+ "#" + path
265
+ else
266
+ HTMLGenerator.gen_url(from_path, path)
267
+ end
268
+ end
269
+
270
+ # Create a list of HtmlMethod objects for each method
271
+ # in the corresponding context object. If the @options.show_all
272
+ # variable is set (corresponding to the <tt>--all</tt> option,
273
+ # we include all methods, otherwise just the public ones.
274
+
275
+ def collect_methods
276
+ list = @context.method_list
277
+ unless @options.show_all
278
+ list = list.find_all {|m| m.visibility == :public || m.force_documentation }
279
+ end
280
+ @methods = list.collect {|m| HtmlMethod.new(m, self, @options) }
281
+ end
282
+
283
+ # Build a summary list of all the methods in this context
284
+ def build_method_summary_list(path_prefix="")
285
+ collect_methods unless @methods
286
+ meths = @methods.sort
287
+ res = []
288
+ meths.each do |meth|
289
+ res << {
290
+ "name" => CGI.escapeHTML(meth.name),
291
+ "aref" => "#{path_prefix}\##{meth.aref}"
292
+ }
293
+ end
294
+ res
295
+ end
296
+
297
+
298
+ # Build a list of aliases fo which we couldn't find a corresponding method
299
+ def build_alias_summary_list
300
+ @context.aliases.map do |al|
301
+ {
302
+ 'old_name' => al.old_name,
303
+ 'new_name' => al.new_name,
304
+ }
305
+ end
306
+ end
307
+
308
+ def build_requires_list(context)
309
+ potentially_referenced_list(context.requires) {|fn| [fn + ".rb"] }
310
+ end
311
+
312
+ def build_include_list(context)
313
+ potentially_referenced_list(context.includes)
314
+ end
315
+
316
+ # Build a list from an array of <i>Htmlxxx</i> items. Look up each
317
+ # in the AllReferences hash: if we find a corresponding entry,
318
+ # we generate a hyperlink to it, otherwise just output the name.
319
+ # However, some names potentially need massaging. For example,
320
+ # you may require a Ruby file without the .rb extension,
321
+ # but the file names we know about may have it. To deal with
322
+ # this, we pass in a block which performs the massaging,
323
+ # returning an array of alternative names to match
324
+
325
+ def potentially_referenced_list(array)
326
+ res = []
327
+ array.each do |i|
328
+ ref = AllReferences[i.name]
329
+ if !ref && block_given?
330
+ possibles = yield(i.name)
331
+ while !ref and !possibles.empty?
332
+ ref = AllReferences[possibles.shift]
333
+ end
334
+ end
335
+ h_name = CGI.escapeHTML(i.name)
336
+ if ref and ref.document_self
337
+ path = url(ref.path)
338
+ res << { "name" => h_name, "aref" => path }
339
+ else
340
+ res << { "name" => h_name }
341
+ end
342
+ end
343
+ res
344
+ end
345
+
346
+ # Build an array of arrays of method details. The outer array has up
347
+ # to six entries, public, private, and protected for both class
348
+ # methods, the other for instance methods. The inner arrays contain
349
+ # a hash for each method
350
+
351
+ def build_method_detail_list
352
+ outer = []
353
+
354
+ for singleton in [true, false]
355
+ for vis in [ :public, :protected, :private ]
356
+ res = []
357
+ @methods.each do |m|
358
+ if m.document_self and m.visibility == vis and m.singleton == singleton
359
+ row = {}
360
+ row["name"] = CGI.escapeHTML(m.name)
361
+ desc = m.description.strip
362
+ row["m_desc"] = desc unless desc.empty?
363
+ row["params"] = m.params
364
+ row["aref"] = m.aref
365
+ row["visibility"] = m.visibility.to_s
366
+
367
+ unless m.aliases.empty?
368
+ row["aka"] = m.aliases.map do |other|
369
+ {
370
+ 'name' => other.name,
371
+ 'aref' => other.viewer.as_href(path)
372
+ }
373
+ end
374
+ end
375
+
376
+ if @options.inline_source
377
+ code = m.source_code
378
+ row["sourcecode"] = code if code
379
+ else
380
+ code = m.src_url
381
+ if code
382
+ row["codeurl"] = code
383
+ row["imgurl"] = m.img_url
384
+ end
385
+ end
386
+ res << row
387
+ end
388
+ end
389
+ if res.size > 0
390
+ outer << {
391
+ "type" => vis.to_s.capitalize,
392
+ "category" => singleton ? "Class" : "Instance",
393
+ "methods" => res
394
+ }
395
+ end
396
+ end
397
+ end
398
+ outer
399
+ end
400
+
401
+ # Build the structured list of classes and modules contained
402
+ # in this context.
403
+
404
+ def build_class_list(level, from)
405
+ res = ""
406
+ prefix = "&nbsp;&nbsp;::" * level;
407
+
408
+ from.modules.sort.each do |mod|
409
+ if mod.document_self
410
+ res <<
411
+ prefix <<
412
+ "Module " <<
413
+ href(url(mod.viewer.path), "link", mod.full_name) <<
414
+ "<br />\n" <<
415
+ build_class_list(level + 1, mod)
416
+ end
417
+ end
418
+
419
+ from.classes.sort.each do |cls|
420
+ if cls.document_self
421
+ res <<
422
+ prefix <<
423
+ "Class " <<
424
+ href(url(cls.viewer.path), "link", cls.full_name) <<
425
+ "<br />\n" <<
426
+ build_class_list(level + 1, cls)
427
+ end
428
+ end
429
+
430
+ res
431
+ end
432
+
433
+ def url(target)
434
+ HTMLGenerator.gen_url(path, target)
435
+ end
436
+
437
+ def aref_to(target)
438
+ if @options.all_one_file
439
+ "#" + target
440
+ else
441
+ url(target)
442
+ end
443
+ end
444
+
445
+ def document_self
446
+ @context.document_self
447
+ end
448
+
449
+ def diagram_reference(diagram)
450
+ res = diagram.gsub(/((?:src|href)=")(.*?)"/) {
451
+ $1 + url($2) + '"'
452
+ }
453
+ res
454
+ end
455
+
456
+ end
457
+
458
+ #####################################################################
459
+ #
460
+ # Wrap a ClassModule context
461
+
462
+ class HtmlClass < ContextUser
463
+
464
+ attr_reader :path
465
+
466
+ def initialize(context, html_file, prefix, options)
467
+ super(context, options)
468
+
469
+ @html_file = html_file
470
+ @is_module = context.is_module?
471
+ @values = {}
472
+
473
+ context.viewer = self
474
+
475
+ if options.all_one_file
476
+ @path = context.full_name
477
+ else
478
+ @path = http_url(context.full_name, prefix)
479
+ end
480
+
481
+ collect_methods
482
+
483
+ AllReferences.add(name, self)
484
+ end
485
+
486
+ # return the relative file name to store this class in,
487
+ # which is also its url
488
+ def http_url(full_name, prefix)
489
+ path = full_name.dup
490
+ if path['<<']
491
+ path.gsub!(/<<\s*(\w*)/) { "from-#$1" }
492
+ end
493
+ File.join(prefix, path.split("::")) + ".html"
494
+ end
495
+
496
+
497
+ def name
498
+ @context.full_name
499
+ end
500
+
501
+ def parent_name
502
+ @context.parent.full_name
503
+ end
504
+
505
+ def index_name
506
+ name
507
+ end
508
+
509
+ def write_on(f)
510
+ value_hash
511
+ template = TemplatePage.new(RDoc::Page::BODY,
512
+ RDoc::Page::CLASS_PAGE,
513
+ RDoc::Page::METHOD_LIST)
514
+ template.write_html_on(f, @values)
515
+ end
516
+
517
+ def value_hash
518
+ class_attribute_values
519
+
520
+ @values["charset"] = @options.charset
521
+ @values["style_url"] = url(CSS_NAME)
522
+
523
+ d = markup(@context.comment)
524
+ @values["description"] = d unless d.empty?
525
+
526
+ ml = build_method_summary_list
527
+ @values["methods"] = ml unless ml.empty?
528
+
529
+ al = build_alias_summary_list
530
+ @values["aliases"] = al unless al.empty?
531
+
532
+ il = build_include_list(@context)
533
+ @values["includes"] = il unless il.empty?
534
+
535
+ al = build_attribute_list
536
+ @values["attributes"] = al unless al.empty?
537
+
538
+ cl = build_class_list(0, @context)
539
+ @values["classlist"] = cl unless cl.empty?
540
+
541
+ mdl = build_method_detail_list
542
+ @values["method_list"] = mdl unless mdl.empty?
543
+ @values
544
+ end
545
+
546
+ def build_attribute_list
547
+ atts = @context.attributes.sort
548
+ res = []
549
+ atts.each do |att|
550
+ res << {
551
+ "name" => CGI.escapeHTML(att.name),
552
+ "rw" => att.rw,
553
+ "a_desc" => markup(att.comment)
554
+ }
555
+ end
556
+ res
557
+ end
558
+
559
+ def class_attribute_values
560
+ h_name = CGI.escapeHTML(name)
561
+
562
+ @values["classmod"] = @is_module ? "Module" : "Class"
563
+ @values["title"] = "#{@values['classmod']}: #{h_name}"
564
+
565
+ c = @context
566
+ c = c.parent while c and !c.diagram
567
+ if c && c.diagram
568
+ @values["diagram"] = diagram_reference(c.diagram)
569
+ end
570
+
571
+ @values["full_name"] = h_name
572
+
573
+ parent_class = @context.superclass
574
+
575
+ if parent_class
576
+ @values["parent"] = CGI.escapeHTML(parent_class)
577
+
578
+ if parent_name
579
+ lookup = parent_name + "::" + parent_class
580
+ else
581
+ lookup = parent_class
582
+ end
583
+
584
+ parent_url = AllReferences[lookup] || AllReferences[parent_class]
585
+
586
+ if parent_url and parent_url.document_self
587
+ @values["par_url"] = aref_to(parent_url.path)
588
+ end
589
+ end
590
+
591
+ files = []
592
+ @context.in_files.each do |f|
593
+ res = {}
594
+ res["full_path"] = CGI.escapeHTML(f.file_absolute_name)
595
+ res["full_path_url"] = aref_to(f.viewer.path) if f.document_self
596
+ files << res
597
+ end
598
+
599
+ @values['infiles'] = files
600
+
601
+ end
602
+
603
+ def <=>(other)
604
+ self.name <=> other.name
605
+ end
606
+
607
+ end
608
+
609
+ #####################################################################
610
+ #
611
+ # Handles the mapping of a file's information to HTML. In reality,
612
+ # a file corresponds to a +TopLevel+ object, containing modules,
613
+ # classes, and top-level methods. In theory it _could_ contain
614
+ # attributes and aliases, but we ignore these for now.
615
+
616
+ class HtmlFile < ContextUser
617
+
618
+ attr_reader :path
619
+ attr_reader :name
620
+
621
+ def initialize(context, options, file_dir)
622
+ super(context, options)
623
+
624
+ @values = {}
625
+
626
+ if options.all_one_file
627
+ @path = filename_to_label
628
+ else
629
+ @path = http_url(file_dir)
630
+ end
631
+
632
+ @name = @context.file_relative_name
633
+
634
+ collect_methods
635
+ AllReferences.add(name, self)
636
+ context.viewer = self
637
+ end
638
+
639
+ def http_url(file_dir)
640
+ File.join(file_dir, @context.file_relative_name.tr('.', '_')) +
641
+ ".html"
642
+ end
643
+
644
+ def filename_to_label
645
+ @context.file_relative_name.gsub(/%|\/|\?|\#/) {|s| '%' + ("%x" % s[0]) }
646
+ end
647
+
648
+ def index_name
649
+ name
650
+ end
651
+
652
+ def parent_name
653
+ nil
654
+ end
655
+
656
+ def value_hash
657
+ file_attribute_values
658
+
659
+ @values["charset"] = @options.charset
660
+ @values["href"] = path
661
+ @values["style_url"] = url(CSS_NAME)
662
+
663
+ if @context.comment
664
+ d = markup(@context.comment)
665
+ @values["description"] = d if d.size > 0
666
+ end
667
+
668
+ ml = build_method_summary_list
669
+ @values["methods"] = ml unless ml.empty?
670
+
671
+ il = build_include_list(@context)
672
+ @values["includes"] = il unless il.empty?
673
+
674
+ rl = build_requires_list(@context)
675
+ @values["requires"] = rl unless rl.empty?
676
+
677
+ cl = build_class_list(0, @context)
678
+ @values["classlist"] = cl unless cl.empty?
679
+
680
+ mdl = build_method_detail_list
681
+ @values["method_list"] = mdl unless mdl.empty?
682
+ @values
683
+ end
684
+
685
+ def write_on(f)
686
+ value_hash
687
+ template = TemplatePage.new(RDoc::Page::BODY,
688
+ RDoc::Page::FILE_PAGE,
689
+ RDoc::Page::METHOD_LIST)
690
+ template.write_html_on(f, @values)
691
+ end
692
+
693
+ def file_attribute_values
694
+ full_path = @context.file_absolute_name
695
+ short_name = File.basename(full_path)
696
+
697
+ @values["title"] = CGI.escapeHTML("File: #{short_name}")
698
+
699
+ if @context.diagram
700
+ @values["diagram"] = diagram_reference(@context.diagram)
701
+ end
702
+
703
+ @values["short_name"] = CGI.escapeHTML(short_name)
704
+ @values["full_path"] = CGI.escapeHTML(full_path)
705
+ @values["dtm_modified"] = @context.file_stat.mtime.to_s
706
+ end
707
+
708
+ def <=>(other)
709
+ self.name <=> other.name
710
+ end
711
+ end
712
+
713
+ #####################################################################
714
+
715
+ class HtmlMethod
716
+ include MarkUp
717
+
718
+ attr_reader :context
719
+ attr_reader :src_url
720
+ attr_reader :img_url
721
+ attr_reader :source_code
722
+
723
+ @@seq = "M000000"
724
+
725
+ @@all_methods = []
726
+
727
+ def HtmlMethod::reset
728
+ @@all_methods = []
729
+ end
730
+
731
+ def initialize(context, html_class, options)
732
+ @context = context
733
+ @html_class = html_class
734
+ @options = options
735
+ @@seq = @@seq.succ
736
+ @seq = @@seq
737
+ @@all_methods << self
738
+
739
+ context.viewer = self
740
+
741
+ if (ts = @context.token_stream)
742
+ @source_code = markup_code(ts)
743
+ unless @options.inline_source
744
+ @src_url = create_source_code_file(@source_code)
745
+ @img_url = HTMLGenerator.gen_url(path, 'source.png')
746
+ end
747
+ end
748
+
749
+ AllReferences.add(name, self)
750
+ end
751
+
752
+ # return a reference to outselves to be used as an href=
753
+ # the form depends on whether we're all in one file
754
+ # or in multiple files
755
+
756
+ def as_href(from_path)
757
+ if @options.all_one_file
758
+ "#" + path
759
+ else
760
+ HTMLGenerator.gen_url(from_path, path)
761
+ end
762
+ end
763
+
764
+ def name
765
+ @context.name
766
+ end
767
+
768
+ def index_name
769
+ "#{@context.name} (#{@html_class.name})"
770
+ end
771
+
772
+ def parent_name
773
+ if @context.parent.parent
774
+ @context.parent.parent.full_name
775
+ else
776
+ nil
777
+ end
778
+ end
779
+
780
+ def aref
781
+ @seq
782
+ end
783
+
784
+ def path
785
+ if @options.all_one_file
786
+ aref
787
+ else
788
+ @html_class.path + "#" + aref
789
+ end
790
+ end
791
+
792
+ def description
793
+ markup(@context.comment)
794
+ end
795
+
796
+ def visibility
797
+ @context.visibility
798
+ end
799
+
800
+ def singleton
801
+ @context.singleton
802
+ end
803
+
804
+ def params
805
+ p = @context.params.gsub(/\s*\#.*/, '')
806
+ p = p.tr("\n", " ").squeeze(" ")
807
+ p = "(" + p + ")" unless p[0] == ?(
808
+
809
+ if (block = @context.block_params)
810
+ block.gsub!(/\s*\#.*/, '')
811
+ block = block.tr("\n", " ").squeeze(" ")
812
+ if block[0] == ?(
813
+ block.sub!(/^\(/, '').sub!(/\)/, '')
814
+ end
815
+ p << " {|#{block}| ...}"
816
+ end
817
+
818
+ CGI.escapeHTML(p)
819
+ end
820
+
821
+ def create_source_code_file(code_body)
822
+ meth_path = @html_class.path.sub(/\.html$/, '.src')
823
+ File.makedirs(meth_path)
824
+ file_path = File.join(meth_path, @seq) + ".html"
825
+
826
+ template = TemplatePage.new(RDoc::Page::SRC_PAGE)
827
+ File.open(file_path, "w") do |f|
828
+ values = {
829
+ 'title' => CGI.escapeHTML(index_name),
830
+ 'code' => code_body,
831
+ 'style_url' => HTMLGenerator.gen_url(file_path, CSS_NAME),
832
+ 'charset' => @options.charset
833
+ }
834
+ template.write_html_on(f, values)
835
+ end
836
+ HTMLGenerator.gen_url(path, file_path)
837
+ end
838
+
839
+ def HtmlMethod.all_methods
840
+ @@all_methods
841
+ end
842
+
843
+ def <=>(other)
844
+ @context <=> other.context
845
+ end
846
+
847
+ ##
848
+ # Given a sequence of source tokens, mark up the source code
849
+ # to make it look purty.
850
+
851
+ def markup_code(tokens)
852
+ src = ""
853
+ tokens.each do |t|
854
+ next unless t
855
+ # p t.class
856
+ style = nil
857
+ text = CGI.escapeHTML(t.text)
858
+ case t
859
+ when RubyToken::TkKW
860
+ style = "kw"
861
+ when RubyToken::TkCOMMENT
862
+ style = "cmt"
863
+ when RubyToken::TkSTRING
864
+ style = "str"
865
+ when RubyToken::TkREGEXP
866
+ style = "re"
867
+ end
868
+ if style
869
+ src << "<span class=\"#{style}\">#{text}</span>"
870
+ else
871
+ src << text
872
+ end
873
+ end
874
+
875
+ add_line_numbers(src) if Options.instance.include_line_numbers
876
+ src
877
+ end
878
+
879
+ # we rely on the fact that the first line of a source code
880
+ # listing has
881
+ # # File xxxxx, line dddd
882
+
883
+ def add_line_numbers(src)
884
+ if src =~ /\A.*, line (\d+)/
885
+ first = $1.to_i - 1
886
+ last = first + src.count("\n")
887
+ size = last.to_s.length
888
+ real_fmt = "%#{size}d: "
889
+ fmt = " " * (size+2)
890
+ src.gsub!(/^/) do
891
+ res = sprintf(fmt, first)
892
+ first += 1
893
+ fmt = real_fmt
894
+ res
895
+ end
896
+ end
897
+ end
898
+
899
+ def document_self
900
+ @context.document_self
901
+ end
902
+
903
+ def aliases
904
+ @context.aliases
905
+ end
906
+ end
907
+
908
+ #####################################################################
909
+
910
+ class HTMLGenerator
911
+
912
+ include MarkUp
913
+
914
+ ##
915
+ # convert a target url to one that is relative to a given
916
+ # path
917
+
918
+ def HTMLGenerator.gen_url(path, target)
919
+ from = File.dirname(path)
920
+ to, to_file = File.split(target)
921
+
922
+ from = from.split("/")
923
+ to = to.split("/")
924
+
925
+ while from.size > 0 and to.size > 0 and from[0] == to[0]
926
+ from.shift
927
+ to.shift
928
+ end
929
+
930
+ from.fill("..")
931
+ from.concat(to)
932
+ from << to_file
933
+ File.join(*from)
934
+ end
935
+
936
+ # Generators may need to return specific subclasses depending
937
+ # on the options they are passed. Because of this
938
+ # we create them using a factory
939
+
940
+ def HTMLGenerator.for(options)
941
+ AllReferences::reset
942
+ HtmlMethod::reset
943
+
944
+ if options.all_one_file
945
+ HTMLGeneratorInOne.new(options)
946
+ else
947
+ HTMLGenerator.new(options)
948
+ end
949
+ end
950
+
951
+ class <<self
952
+ protected :new
953
+ end
954
+
955
+ # Set up a new HTML generator. Basically all we do here is load
956
+ # up the correct output temlate
957
+
958
+ def initialize(options) #:not-new:
959
+ @options = options
960
+ load_html_template
961
+ end
962
+
963
+
964
+ ##
965
+ # Build the initial indices and output objects
966
+ # based on an array of TopLevel objects containing
967
+ # the extracted information.
968
+
969
+ def generate(info)
970
+ @info = info
971
+ @files = []
972
+ @classes = []
973
+ @hyperlinks = {}
974
+
975
+ # write_source_icon
976
+ write_style_sheet
977
+ gen_sub_directories()
978
+ build_indices
979
+ generate_html
980
+ end
981
+
982
+ private
983
+
984
+ ##
985
+ # Load up the HTML template specified in the options
986
+ #
987
+ def load_html_template
988
+ template = File.join("rdoc/generators/template",
989
+ @options.generator.key, @options.template)
990
+ require template
991
+ extend RDoc::Page
992
+ rescue LoadError
993
+ $stderr.puts "Could not find HTML template '#{template}'"
994
+ exit 99
995
+ end
996
+
997
+ ##
998
+ # Write out the style sheet used by the main frames
999
+ #
1000
+
1001
+ def write_style_sheet
1002
+ template = TemplatePage.new(RDoc::Page::STYLE)
1003
+ File.open(CSS_NAME, "w") do |f|
1004
+ values = { "fonts" => RDoc::Page::FONTS }
1005
+ template.write_html_on(f, values)
1006
+ end
1007
+ end
1008
+
1009
+ ##
1010
+ # See the comments at the top for a description of the
1011
+ # directory structure
1012
+
1013
+ def gen_sub_directories
1014
+ File.makedirs(FILE_DIR, CLASS_DIR)
1015
+ rescue
1016
+ $stderr.puts $!.message
1017
+ exit 1
1018
+ end
1019
+
1020
+ ##
1021
+ # Generate:
1022
+ #
1023
+ # * a list of HtmlFile objects for each TopLevel object.
1024
+ # * a list of HtmlClass objects for each first level
1025
+ # class or module in the TopLevel objects
1026
+ # * a complete list of all hyperlinkable terms (file,
1027
+ # class, module, and method names)
1028
+
1029
+ def build_indices
1030
+
1031
+ @info.each do |toplevel|
1032
+ @files << HtmlFile.new(toplevel, @options, FILE_DIR)
1033
+ end
1034
+
1035
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
1036
+ build_class_list(cls, @files[0], CLASS_DIR)
1037
+ end
1038
+ end
1039
+
1040
+ def build_class_list(from, html_file, class_dir)
1041
+ @classes << HtmlClass.new(from, html_file, class_dir, @options)
1042
+ from.each_classmodule do |mod|
1043
+ build_class_list(mod, html_file, class_dir)
1044
+ end
1045
+ end
1046
+
1047
+ ##
1048
+ # Generate all the HTML
1049
+ #
1050
+ def generate_html
1051
+ # the individual descriptions for files and classes
1052
+ gen_into(@files)
1053
+ gen_into(@classes)
1054
+ # and the index files
1055
+ gen_file_index
1056
+ gen_class_index
1057
+ gen_method_index
1058
+ gen_main_index
1059
+
1060
+ # this method is defined in the template file
1061
+ write_extra_pages if defined? write_extra_pages
1062
+ end
1063
+
1064
+ def gen_into(list)
1065
+ list.each do |item|
1066
+ if item.document_self
1067
+ op_file = item.path
1068
+ File.makedirs(File.dirname(op_file))
1069
+ File.open(op_file, "w") { |file| item.write_on(file) }
1070
+ end
1071
+ end
1072
+
1073
+ end
1074
+
1075
+ def gen_file_index
1076
+ gen_an_index(@files, 'Files',
1077
+ RDoc::Page::FILE_INDEX,
1078
+ "fr_file_index.html")
1079
+ end
1080
+
1081
+ def gen_class_index
1082
+ gen_an_index(@classes, 'Classes',
1083
+ RDoc::Page::CLASS_INDEX,
1084
+ "fr_class_index.html")
1085
+ end
1086
+
1087
+ def gen_method_index
1088
+ gen_an_index(HtmlMethod.all_methods, 'Methods',
1089
+ RDoc::Page::METHOD_INDEX,
1090
+ "fr_method_index.html")
1091
+ end
1092
+
1093
+
1094
+ def gen_an_index(collection, title, template, filename)
1095
+ template = TemplatePage.new(RDoc::Page::FR_INDEX_BODY, template)
1096
+ res = []
1097
+ collection.sort.each do |f|
1098
+ if f.document_self
1099
+ res << { "href" => f.path, "name" => f.index_name }
1100
+ end
1101
+ end
1102
+
1103
+ values = {
1104
+ "entries" => res,
1105
+ 'list_title' => CGI.escapeHTML(title),
1106
+ 'index_url' => main_url,
1107
+ 'charset' => @options.charset
1108
+ }
1109
+
1110
+ File.open(filename, "w") do |f|
1111
+ template.write_html_on(f, values)
1112
+ end
1113
+ end
1114
+
1115
+ # The main index page is mostly a template frameset, but includes
1116
+ # the initial page. If the <tt>--main</tt> option was given,
1117
+ # we use this as our main page, otherwise we use the
1118
+ # first file specified on the command line.
1119
+
1120
+ def gen_main_index
1121
+ template = TemplatePage.new(RDoc::Page::INDEX)
1122
+ File.open("index.html", "w") do |f|
1123
+ values = {
1124
+ "initial_page" => main_url,
1125
+ 'title' => CGI.escapeHTML(@options.title),
1126
+ 'charset' => @options.charset
1127
+ }
1128
+ template.write_html_on(f, values)
1129
+ end
1130
+ end
1131
+
1132
+ # return the url of the main page
1133
+ def main_url
1134
+ main_page = @options.main_page
1135
+ ref = nil
1136
+ if main_page
1137
+ ref = AllReferences[main_page]
1138
+ if ref
1139
+ ref = ref.path
1140
+ else
1141
+ $stderr.puts "Could not find main page #{main_page}"
1142
+ end
1143
+ end
1144
+
1145
+ ref = @files[0].path unless ref
1146
+
1147
+ ref
1148
+ end
1149
+
1150
+
1151
+ end
1152
+
1153
+
1154
+ ######################################################################
1155
+
1156
+
1157
+ class HTMLGeneratorInOne < HTMLGenerator
1158
+
1159
+ def initialize(*args)
1160
+ super
1161
+ end
1162
+
1163
+ ##
1164
+ # Build the initial indices and output objects
1165
+ # based on an array of TopLevel objects containing
1166
+ # the extracted information.
1167
+
1168
+ def generate(info)
1169
+ @info = info
1170
+ @files = []
1171
+ @classes = []
1172
+ @hyperlinks = {}
1173
+
1174
+ build_indices
1175
+ generate_xml
1176
+ end
1177
+
1178
+
1179
+ ##
1180
+ # Generate:
1181
+ #
1182
+ # * a list of HtmlFile objects for each TopLevel object.
1183
+ # * a list of HtmlClass objects for each first level
1184
+ # class or module in the TopLevel objects
1185
+ # * a complete list of all hyperlinkable terms (file,
1186
+ # class, module, and method names)
1187
+
1188
+ def build_indices
1189
+
1190
+ @info.each do |toplevel|
1191
+ @files << HtmlFile.new(toplevel, @options, FILE_DIR)
1192
+ end
1193
+
1194
+ RDoc::TopLevel.all_classes_and_modules.each do |cls|
1195
+ build_class_list(cls, @files[0], CLASS_DIR)
1196
+ end
1197
+ end
1198
+
1199
+ def build_class_list(from, html_file, class_dir)
1200
+ @classes << HtmlClass.new(from, html_file, class_dir, @options)
1201
+ from.each_classmodule do |mod|
1202
+ build_class_list(mod, html_file, class_dir)
1203
+ end
1204
+ end
1205
+
1206
+ ##
1207
+ # Generate all the HTML. For the one-file case, we generate
1208
+ # all the information in to one big hash
1209
+ #
1210
+ def generate_xml
1211
+ values = {
1212
+ 'charset' => @options.charset,
1213
+ 'files' => gen_into(@files),
1214
+ 'classes' => gen_into(@classes),
1215
+ 'title' => CGI.escapeHTML(@options.title),
1216
+ }
1217
+
1218
+ # this method is defined in the template file
1219
+ write_extra_pages if defined? write_extra_pages
1220
+
1221
+ template = TemplatePage.new(RDoc::Page::ONE_PAGE)
1222
+
1223
+ if @options.op_name
1224
+ opfile = File.open(@options.op_name, "w")
1225
+ else
1226
+ opfile = $stdout
1227
+ end
1228
+ template.write_html_on(opfile, values)
1229
+ end
1230
+
1231
+ def gen_into(list)
1232
+ res = []
1233
+ list.each do |item|
1234
+ res << item.value_hash
1235
+ end
1236
+ res
1237
+ end
1238
+
1239
+ def gen_file_index
1240
+ gen_an_index(@files, 'Files')
1241
+ end
1242
+
1243
+ def gen_class_index
1244
+ gen_an_index(@classes, 'Classes')
1245
+ end
1246
+
1247
+ def gen_method_index
1248
+ gen_an_index(HtmlMethod.all_methods, 'Methods')
1249
+ end
1250
+
1251
+
1252
+ def gen_an_index(collection, title)
1253
+ res = []
1254
+ collection.sort.each do |f|
1255
+ if f.document_self
1256
+ res << { "href" => f.path, "name" => f.index_name }
1257
+ end
1258
+ end
1259
+
1260
+ return {
1261
+ "entries" => res,
1262
+ 'list_title' => title,
1263
+ 'index_url' => main_url,
1264
+ }
1265
+ end
1266
+
1267
+ end
1268
+ end