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.
- data/Gemfile +8 -0
- data/Gemfile.lock +22 -0
- data/LICENSE.md +23 -0
- data/README.rdoc +59 -0
- data/Rakefile +32 -0
- data/VERSION +1 -0
- data/doc/BUGS +2 -0
- data/doc/examples/README +6 -0
- data/doc/examples/connection.rb +16 -0
- data/doc/examples/connection_auto.rb +22 -0
- data/doc/examples/connection_ctor.rb +18 -0
- data/doc/examples/connection_default.rb +15 -0
- data/doc/examples/connection_exec.rb +18 -0
- data/doc/examples/connection_manual.rb +12 -0
- data/doc/examples/connection_wrapped_new.rb +13 -0
- data/doc/examples/connection_wrapped_open.rb +13 -0
- data/doc/examples/cursor.rb +38 -0
- data/doc/examples/include_module.rb +9 -0
- data/doc/examples/include_module2.rb +12 -0
- data/doc/examples/insert.rb +30 -0
- data/doc/examples/insert2.rb +36 -0
- data/doc/examples/insert_bytea.rb +16 -0
- data/doc/examples/insert_bytea_array.rb +17 -0
- data/doc/examples/insert_default_values.rb +16 -0
- data/doc/examples/insert_insert.rb +16 -0
- data/doc/examples/insert_insert_default.rb +16 -0
- data/doc/examples/insert_insert_select.rb +20 -0
- data/doc/examples/insert_select.rb +20 -0
- data/doc/examples/interval.rb +17 -0
- data/doc/examples/savepoint.rb +38 -0
- data/doc/examples/select.rb +33 -0
- data/doc/examples/select2.rb +36 -0
- data/doc/examples/select_cross_join.rb +18 -0
- data/doc/examples/select_distinct.rb +18 -0
- data/doc/examples/select_distinct_on +19 -0
- data/doc/examples/select_for_update.rb +18 -0
- data/doc/examples/select_from.rb +17 -0
- data/doc/examples/select_from_subselect.rb +20 -0
- data/doc/examples/select_group_by.rb +19 -0
- data/doc/examples/select_having.rb +20 -0
- data/doc/examples/select_join_on.rb +18 -0
- data/doc/examples/select_join_using.rb +18 -0
- data/doc/examples/select_limit.rb +19 -0
- data/doc/examples/select_natural_join.rb +18 -0
- data/doc/examples/select_offset.rb +19 -0
- data/doc/examples/select_order_by.rb +20 -0
- data/doc/examples/select_select.rb +30 -0
- data/doc/examples/select_select_alias.rb +30 -0
- data/doc/examples/select_select_expression.rb +31 -0
- data/doc/examples/select_select_literal.rb +24 -0
- data/doc/examples/select_union.rb +21 -0
- data/doc/examples/select_where_array.rb +18 -0
- data/doc/examples/select_where_in.rb +18 -0
- data/doc/examples/select_where_string.rb +18 -0
- data/doc/examples/simple.rb +34 -0
- data/doc/examples/transaction.rb +30 -0
- data/doc/examples/transaction_abort.rb +30 -0
- data/doc/examples/transaction_commit.rb +34 -0
- data/doc/examples/translate_substitute_values.rb +17 -0
- data/doc/examples/update.rb +32 -0
- data/doc/examples/update2.rb +44 -0
- data/doc/examples/update_only.rb +17 -0
- data/doc/examples/update_set.rb +17 -0
- data/doc/examples/update_set_array.rb +16 -0
- data/doc/examples/update_set_bytea.rb +16 -0
- data/doc/examples/update_set_expression.rb +16 -0
- data/doc/examples/update_set_subselect.rb +20 -0
- data/doc/examples/update_where.rb +17 -0
- data/doc/examples/use_prefix.rb +8 -0
- data/doc/examples/use_prefix2.rb +11 -0
- data/doc/index.html +31 -0
- data/doc/insertexamples.rb +9 -0
- data/doc/makemanual +4 -0
- data/doc/makerdoc +5 -0
- data/doc/manual.dbk +622 -0
- data/lib/sqlpostgres/Connection.rb +198 -0
- data/lib/sqlpostgres/Cursor.rb +157 -0
- data/lib/sqlpostgres/Delete.rb +67 -0
- data/lib/sqlpostgres/Exceptions.rb +15 -0
- data/lib/sqlpostgres/Insert.rb +279 -0
- data/lib/sqlpostgres/NullConnection.rb +22 -0
- data/lib/sqlpostgres/PgBit.rb +73 -0
- data/lib/sqlpostgres/PgBox.rb +37 -0
- data/lib/sqlpostgres/PgCidr.rb +21 -0
- data/lib/sqlpostgres/PgCircle.rb +75 -0
- data/lib/sqlpostgres/PgInet.rb +21 -0
- data/lib/sqlpostgres/PgInterval.rb +208 -0
- data/lib/sqlpostgres/PgLineSegment.rb +37 -0
- data/lib/sqlpostgres/PgMacAddr.rb +21 -0
- data/lib/sqlpostgres/PgPath.rb +64 -0
- data/lib/sqlpostgres/PgPoint.rb +65 -0
- data/lib/sqlpostgres/PgPolygon.rb +56 -0
- data/lib/sqlpostgres/PgTime.rb +77 -0
- data/lib/sqlpostgres/PgTimeWithTimeZone.rb +98 -0
- data/lib/sqlpostgres/PgTimestamp.rb +93 -0
- data/lib/sqlpostgres/PgTwoPoints.rb +54 -0
- data/lib/sqlpostgres/PgType.rb +34 -0
- data/lib/sqlpostgres/PgWrapper.rb +41 -0
- data/lib/sqlpostgres/Savepoint.rb +98 -0
- data/lib/sqlpostgres/Select.rb +855 -0
- data/lib/sqlpostgres/Transaction.rb +120 -0
- data/lib/sqlpostgres/Translate.rb +436 -0
- data/lib/sqlpostgres/Update.rb +188 -0
- data/lib/sqlpostgres.rb +67 -0
- data/test/Assert.rb +72 -0
- data/test/Connection.test.rb +246 -0
- data/test/Cursor.test.rb +190 -0
- data/test/Delete.test.rb +68 -0
- data/test/Insert.test.rb +123 -0
- data/test/MockPGconn.rb +62 -0
- data/test/NullConnection.test.rb +32 -0
- data/test/PgBit.test.rb +98 -0
- data/test/PgBox.test.rb +108 -0
- data/test/PgCidr.test.rb +61 -0
- data/test/PgCircle.test.rb +107 -0
- data/test/PgInet.test.rb +61 -0
- data/test/PgInterval.test.rb +180 -0
- data/test/PgLineSegment.test.rb +108 -0
- data/test/PgMacAddr.test.rb +61 -0
- data/test/PgPath.test.rb +106 -0
- data/test/PgPoint.test.rb +100 -0
- data/test/PgPolygon.test.rb +95 -0
- data/test/PgTime.test.rb +120 -0
- data/test/PgTimeWithTimeZone.test.rb +117 -0
- data/test/PgTimestamp.test.rb +134 -0
- data/test/RandomThings.rb +25 -0
- data/test/Savepoint.test.rb +286 -0
- data/test/Select.test.rb +930 -0
- data/test/Test.rb +62 -0
- data/test/TestConfig.rb +21 -0
- data/test/TestSetup.rb +13 -0
- data/test/TestUtil.rb +92 -0
- data/test/Transaction.test.rb +275 -0
- data/test/Translate.test.rb +354 -0
- data/test/Update.test.rb +227 -0
- data/test/roundtrip.test.rb +565 -0
- data/test/test +34 -0
- data/tools/exampleinserter/ExampleInserter.rb +177 -0
- data/tools/rdoc/ChangeLog +796 -0
- data/tools/rdoc/EXAMPLE.rb +48 -0
- data/tools/rdoc/MANIFEST +58 -0
- data/tools/rdoc/Makefile +27 -0
- data/tools/rdoc/NEW_FEATURES +226 -0
- data/tools/rdoc/README +390 -0
- data/tools/rdoc/ToDo +6 -0
- data/tools/rdoc/contrib/Index +6 -0
- data/tools/rdoc/contrib/xslfo/ChangeLog +181 -0
- data/tools/rdoc/contrib/xslfo/README +106 -0
- data/tools/rdoc/contrib/xslfo/TODO +10 -0
- data/tools/rdoc/contrib/xslfo/convert.xsl +151 -0
- data/tools/rdoc/contrib/xslfo/demo/README +21 -0
- data/tools/rdoc/contrib/xslfo/demo/rdocfo +99 -0
- data/tools/rdoc/contrib/xslfo/fcm.xsl +54 -0
- data/tools/rdoc/contrib/xslfo/files.xsl +62 -0
- data/tools/rdoc/contrib/xslfo/labeled-lists.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/lists.xsl +44 -0
- data/tools/rdoc/contrib/xslfo/modules.xsl +152 -0
- data/tools/rdoc/contrib/xslfo/rdoc.xsl +75 -0
- data/tools/rdoc/contrib/xslfo/source.xsl +66 -0
- data/tools/rdoc/contrib/xslfo/styles.xsl +69 -0
- data/tools/rdoc/contrib/xslfo/tables.xsl +67 -0
- data/tools/rdoc/contrib/xslfo/utils.xsl +21 -0
- data/tools/rdoc/debian/changelog +33 -0
- data/tools/rdoc/debian/compat +1 -0
- data/tools/rdoc/debian/control +20 -0
- data/tools/rdoc/debian/copyright +10 -0
- data/tools/rdoc/debian/dirs +2 -0
- data/tools/rdoc/debian/docs +2 -0
- data/tools/rdoc/debian/rdoc.1 +252 -0
- data/tools/rdoc/debian/rdoc.manpages +1 -0
- data/tools/rdoc/debian/rdoc.pod +149 -0
- data/tools/rdoc/debian/rules +9 -0
- data/tools/rdoc/dot/dot.rb +255 -0
- data/tools/rdoc/etc/rdoc.dtd +203 -0
- data/tools/rdoc/install.rb +137 -0
- data/tools/rdoc/markup/install.rb +43 -0
- data/tools/rdoc/markup/sample/sample.rb +42 -0
- data/tools/rdoc/markup/simple_markup/fragments.rb +323 -0
- data/tools/rdoc/markup/simple_markup/inline.rb +348 -0
- data/tools/rdoc/markup/simple_markup/lines.rb +147 -0
- data/tools/rdoc/markup/simple_markup/preprocess.rb +68 -0
- data/tools/rdoc/markup/simple_markup/to_html.rb +281 -0
- data/tools/rdoc/markup/simple_markup.rb +474 -0
- data/tools/rdoc/markup/test/AllTests.rb +2 -0
- data/tools/rdoc/markup/test/TestInline.rb +151 -0
- data/tools/rdoc/markup/test/TestParse.rb +411 -0
- data/tools/rdoc/rdoc/code_objects.rb +536 -0
- data/tools/rdoc/rdoc/diagram.rb +331 -0
- data/tools/rdoc/rdoc/generators/chm_generator.rb +112 -0
- data/tools/rdoc/rdoc/generators/html_generator.rb +1268 -0
- data/tools/rdoc/rdoc/generators/template/chm/chm.rb +86 -0
- data/tools/rdoc/rdoc/generators/template/html/html.rb +705 -0
- data/tools/rdoc/rdoc/generators/template/html/kilmer.rb +377 -0
- data/tools/rdoc/rdoc/generators/template/xml/rdf.rb +110 -0
- data/tools/rdoc/rdoc/generators/template/xml/xml.rb +110 -0
- data/tools/rdoc/rdoc/generators/xml_generator.rb +130 -0
- data/tools/rdoc/rdoc/options.rb +451 -0
- data/tools/rdoc/rdoc/parsers/parse_c.rb +287 -0
- data/tools/rdoc/rdoc/parsers/parse_f95.rb +118 -0
- data/tools/rdoc/rdoc/parsers/parse_rb.rb +2311 -0
- data/tools/rdoc/rdoc/parsers/parse_simple.rb +37 -0
- data/tools/rdoc/rdoc/parsers/parserfactory.rb +75 -0
- data/tools/rdoc/rdoc/rdoc.rb +219 -0
- data/tools/rdoc/rdoc/template.rb +234 -0
- data/tools/rdoc/rdoc/tokenstream.rb +25 -0
- data/tools/rdoc/rdoc.rb +9 -0
- metadata +291 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Parse a non-source file. We basically take the whole thing
|
|
2
|
+
# as one big comment. If the first character in the file
|
|
3
|
+
# is '#', we strip leading pound signs.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
require "rdoc/code_objects"
|
|
7
|
+
require "markup/simple_markup/preprocess"
|
|
8
|
+
|
|
9
|
+
module RDoc
|
|
10
|
+
# See rdoc/parsers/parse_c.rb
|
|
11
|
+
|
|
12
|
+
class SimpleParser
|
|
13
|
+
|
|
14
|
+
# prepare to parse a plain file
|
|
15
|
+
def initialize(top_level, file_name, body, options)
|
|
16
|
+
|
|
17
|
+
preprocess = SM::PreProcess.new(file_name, options.rdoc_include)
|
|
18
|
+
|
|
19
|
+
preprocess.handle(body) do |directive, param|
|
|
20
|
+
$stderr.puts "Unrecognized directive '#{directive}' in #{file_name}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@body = body
|
|
24
|
+
@options = options
|
|
25
|
+
@top_level = top_level
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Extract the file contents and attach them to the toplevel as a
|
|
29
|
+
# comment
|
|
30
|
+
|
|
31
|
+
def scan
|
|
32
|
+
# @body.gsub(/^(\s\n)+/, '')
|
|
33
|
+
@top_level.comment = @body
|
|
34
|
+
@top_level
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require "rdoc/parsers/parse_simple"
|
|
2
|
+
|
|
3
|
+
module RDoc
|
|
4
|
+
|
|
5
|
+
# A parser is simple a class that implements
|
|
6
|
+
#
|
|
7
|
+
# #initialize(file_name, body, options)
|
|
8
|
+
#
|
|
9
|
+
# and
|
|
10
|
+
#
|
|
11
|
+
# #scan
|
|
12
|
+
#
|
|
13
|
+
# The initialize method takes a file name to be used, the body of the
|
|
14
|
+
# file, and an RDoc::Options object. The scan method is then called
|
|
15
|
+
# to return an appropriately parsed TopLevel code object.
|
|
16
|
+
|
|
17
|
+
# The ParseFactory is used to redirect to the correct parser given a filename
|
|
18
|
+
# extension. This magic works because individual parsers have to register
|
|
19
|
+
# themselves with us as they are loaded in. The do this using the following
|
|
20
|
+
# incantation
|
|
21
|
+
#
|
|
22
|
+
#
|
|
23
|
+
# require "rdoc/parsers/parsefactory"
|
|
24
|
+
#
|
|
25
|
+
# module RDoc
|
|
26
|
+
#
|
|
27
|
+
# class XyzParser
|
|
28
|
+
# extend ParseFactory <<<<
|
|
29
|
+
# parse_files_matching /\.xyz$/ <<<<
|
|
30
|
+
#
|
|
31
|
+
# def initialize(file_name, body, options)
|
|
32
|
+
# ...
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# def scan
|
|
36
|
+
# ...
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
module ParserFactory
|
|
44
|
+
|
|
45
|
+
@@parsers = []
|
|
46
|
+
|
|
47
|
+
Parsers = Struct.new(:regexp, :parser)
|
|
48
|
+
|
|
49
|
+
# Record the fact that a particular class parses files that
|
|
50
|
+
# match a given extension
|
|
51
|
+
|
|
52
|
+
def parse_files_matching(regexp)
|
|
53
|
+
@@parsers.unshift Parsers.new(regexp, self)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Return a parser that can handle a particular extension
|
|
57
|
+
|
|
58
|
+
def ParserFactory.can_parse(file_name)
|
|
59
|
+
@@parsers.find {|p| p.regexp.match(file_name) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Find the correct parser for a particular file name. Return a
|
|
63
|
+
# SimpleParser for ones that we don't know
|
|
64
|
+
|
|
65
|
+
def ParserFactory.parser_for(top_level, file_name, body, options)
|
|
66
|
+
parser_description = can_parse(file_name)
|
|
67
|
+
if parser_description
|
|
68
|
+
parser = parser_description.parser
|
|
69
|
+
else
|
|
70
|
+
parser = SimpleParser
|
|
71
|
+
end
|
|
72
|
+
parser.new(top_level, file_name, body, options)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# See README.
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
RDOC_VERSION = "0.9.0"
|
|
6
|
+
|
|
7
|
+
rcs = '$Date: 2003/10/10 08:00:05 $ $Revision: 1.1 $'.
|
|
8
|
+
gsub(/\$/, '').
|
|
9
|
+
sub(/Date: /, ': ').
|
|
10
|
+
sub(/ Revision: (\S+)/) { "(#$1)" }
|
|
11
|
+
|
|
12
|
+
VERSION_STRING = %{RDoc V} + RDOC_VERSION + rcs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
require 'rdoc/parsers/parse_rb.rb'
|
|
16
|
+
require 'rdoc/parsers/parse_c.rb'
|
|
17
|
+
require 'rdoc/parsers/parse_f95.rb'
|
|
18
|
+
|
|
19
|
+
require 'rdoc/parsers/parse_simple.rb'
|
|
20
|
+
require 'rdoc/options'
|
|
21
|
+
|
|
22
|
+
require 'rdoc/diagram'
|
|
23
|
+
|
|
24
|
+
require 'find'
|
|
25
|
+
require 'ftools'
|
|
26
|
+
|
|
27
|
+
# We put rdoc stuff in the RDoc module to avoid namespace
|
|
28
|
+
# clutter.
|
|
29
|
+
#
|
|
30
|
+
# ToDo: This isn't universally true.
|
|
31
|
+
|
|
32
|
+
module RDoc
|
|
33
|
+
|
|
34
|
+
# Exception thrown by any rdoc error. Only the #message part is
|
|
35
|
+
# of use externally.
|
|
36
|
+
|
|
37
|
+
class RDocError < Exception
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Encapsulate the production of rdoc documentation. Basically
|
|
41
|
+
# you can use this as you would invoke rdoc from the command
|
|
42
|
+
# line:
|
|
43
|
+
#
|
|
44
|
+
# rdoc = RDoc::RDoc.new
|
|
45
|
+
# rdoc.document(args)
|
|
46
|
+
#
|
|
47
|
+
# where _args_ is an array of strings, each corresponding to
|
|
48
|
+
# an argument you'd give rdoc on the command line. See rdoc/rdoc.rb
|
|
49
|
+
# for details.
|
|
50
|
+
|
|
51
|
+
class RDoc
|
|
52
|
+
|
|
53
|
+
##
|
|
54
|
+
# This is the list of output generators that we
|
|
55
|
+
# support
|
|
56
|
+
|
|
57
|
+
Generator = Struct.new(:file_name, :class_name, :key)
|
|
58
|
+
|
|
59
|
+
GENERATORS = {}
|
|
60
|
+
$:.collect {|d|
|
|
61
|
+
File::expand_path(d)
|
|
62
|
+
}.find_all {|d|
|
|
63
|
+
File::directory?("#{d}/rdoc/generators")
|
|
64
|
+
}.each {|dir|
|
|
65
|
+
Dir::entries("#{dir}/rdoc/generators").each {|gen|
|
|
66
|
+
next unless /(\w+)_generator.rb$/ =~ gen
|
|
67
|
+
type = $1
|
|
68
|
+
unless GENERATORS.has_key? type
|
|
69
|
+
GENERATORS[type] = Generator.new("rdoc/generators/#{gen}",
|
|
70
|
+
"#{type.upcase}Generator".intern,
|
|
71
|
+
type)
|
|
72
|
+
end
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#######
|
|
77
|
+
private
|
|
78
|
+
#######
|
|
79
|
+
|
|
80
|
+
##
|
|
81
|
+
# Report an error message and exit
|
|
82
|
+
|
|
83
|
+
def error(msg)
|
|
84
|
+
raise RDocError.new(msg)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
##
|
|
88
|
+
# Create an output dir if it doesn't exist. If it does
|
|
89
|
+
# exist, but doesn't contain the flag file <tt>created.rid</tt>
|
|
90
|
+
# then we refuse to use it, as we may clobber some
|
|
91
|
+
# manually generated documentation
|
|
92
|
+
|
|
93
|
+
def setup_output_dir(op_dir)
|
|
94
|
+
flag_file = File.join(op_dir, "created.rid")
|
|
95
|
+
if File.exist?(op_dir)
|
|
96
|
+
unless File.directory?(op_dir)
|
|
97
|
+
error "'#{op_dir}' exists, and is not a directory"
|
|
98
|
+
end
|
|
99
|
+
unless File.file?(flag_file)
|
|
100
|
+
error "\nDirectory #{op_dir} already exists, but it looks like it\n" +
|
|
101
|
+
"isn't an RDoc directory. Because RDoc doesn't want to risk\n" +
|
|
102
|
+
"destroying any of your existing files, you'll need to\n" +
|
|
103
|
+
"specify a different output directory name (using the\n" +
|
|
104
|
+
"--op <dir> option).\n\n"
|
|
105
|
+
end
|
|
106
|
+
else
|
|
107
|
+
File.makedirs(op_dir)
|
|
108
|
+
end
|
|
109
|
+
File.open(flag_file, "w") {|f| f.puts Time.now }
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
# Given a list of files and directories, create a list
|
|
114
|
+
# of all the Ruby files they contain.
|
|
115
|
+
|
|
116
|
+
def normalized_file_list(options, *relative_files)
|
|
117
|
+
file_list = []
|
|
118
|
+
|
|
119
|
+
relative_files.each do |rel_file_name|
|
|
120
|
+
|
|
121
|
+
case type = File.ftype(rel_file_name)
|
|
122
|
+
when "file"
|
|
123
|
+
file_list << rel_file_name
|
|
124
|
+
when "directory"
|
|
125
|
+
next if options.exclude && options.exclude =~ rel_file_name
|
|
126
|
+
Find.find(rel_file_name) do |fn|
|
|
127
|
+
next if options.exclude && options.exclude =~ fn
|
|
128
|
+
next unless ParserFactory.can_parse(fn)
|
|
129
|
+
next unless File.file?(fn)
|
|
130
|
+
|
|
131
|
+
file_list << fn.sub(%r{\./}, '')
|
|
132
|
+
end
|
|
133
|
+
else
|
|
134
|
+
raise RDocError.new("I can't deal with a #{type} #{rel_file_name}")
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
file_list
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Parse each file on the command line, recursively entering
|
|
141
|
+
# directories
|
|
142
|
+
|
|
143
|
+
def parse_files(options)
|
|
144
|
+
|
|
145
|
+
file_info = []
|
|
146
|
+
|
|
147
|
+
files = options.files
|
|
148
|
+
files = ["."] if files.empty?
|
|
149
|
+
|
|
150
|
+
file_list = normalized_file_list(options, *files)
|
|
151
|
+
|
|
152
|
+
file_list.each do |fn|
|
|
153
|
+
$stderr.printf("\n%35s: ", File.basename(fn)) unless options.quiet
|
|
154
|
+
|
|
155
|
+
content = File.open(fn, "r") {|f| f.read}
|
|
156
|
+
|
|
157
|
+
top_level = TopLevel.new(fn)
|
|
158
|
+
parser = ParserFactory.parser_for(top_level, fn, content, options)
|
|
159
|
+
file_info << parser.scan
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
file_info
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
public
|
|
167
|
+
|
|
168
|
+
###################################################################
|
|
169
|
+
#
|
|
170
|
+
# Format up one or more files according to the given arguments.
|
|
171
|
+
# For simplicity, _argv_ is an array of strings, equivalent to the
|
|
172
|
+
# strings that would be passed on the command line. (This isn't a
|
|
173
|
+
# coincidence, as we _do_ pass in ARGV when running
|
|
174
|
+
# interactively). For a list of options, see rdoc/rdoc.rb. By
|
|
175
|
+
# default, output will be stored in a directory called +doc+ below
|
|
176
|
+
# the current directory, so make sure you're somewhere writable
|
|
177
|
+
# before invoking.
|
|
178
|
+
#
|
|
179
|
+
# Throws: RDocError on error
|
|
180
|
+
|
|
181
|
+
def document(argv)
|
|
182
|
+
|
|
183
|
+
TopLevel::reset
|
|
184
|
+
|
|
185
|
+
options = Options.instance
|
|
186
|
+
options.parse(argv, GENERATORS)
|
|
187
|
+
|
|
188
|
+
file_info = parse_files(options)
|
|
189
|
+
|
|
190
|
+
gen = options.generator
|
|
191
|
+
|
|
192
|
+
$stderr.puts "\nGenerating #{gen.key.upcase}..." unless options.quiet
|
|
193
|
+
|
|
194
|
+
require gen.file_name
|
|
195
|
+
|
|
196
|
+
gen_class = Generators.const_get(gen.class_name)
|
|
197
|
+
|
|
198
|
+
unless file_info.empty?
|
|
199
|
+
gen = gen_class.for(options)
|
|
200
|
+
|
|
201
|
+
pwd = Dir.pwd
|
|
202
|
+
|
|
203
|
+
unless options.all_one_file
|
|
204
|
+
setup_output_dir(options.op_dir)
|
|
205
|
+
Dir.chdir(options.op_dir)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
begin
|
|
209
|
+
Diagram.new(file_info, options).draw if options.diagram
|
|
210
|
+
gen.generate(file_info)
|
|
211
|
+
ensure
|
|
212
|
+
Dir.chdir(pwd)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Cheap-n-cheerful HTML page template system. You create a
|
|
2
|
+
# template containing:
|
|
3
|
+
#
|
|
4
|
+
# * variable names between percent signs (<tt>%fred%</tt>)
|
|
5
|
+
# * blocks of repeating stuff:
|
|
6
|
+
#
|
|
7
|
+
# START:key
|
|
8
|
+
# ... stuff
|
|
9
|
+
# END:key
|
|
10
|
+
#
|
|
11
|
+
# You feed the code a hash. For simple variables, the values
|
|
12
|
+
# are resolved directly from the hash. For blocks, the hash entry
|
|
13
|
+
# corresponding to +key+ will be an array of hashes. The block will
|
|
14
|
+
# be generated once for each entry. Blocks can be nested arbitrarily
|
|
15
|
+
# deeply.
|
|
16
|
+
#
|
|
17
|
+
# The template may also contain
|
|
18
|
+
#
|
|
19
|
+
# IF:key
|
|
20
|
+
# ... stuff
|
|
21
|
+
# ENDIF:key
|
|
22
|
+
#
|
|
23
|
+
# _stuff_ will only be included in the output if the corresponding
|
|
24
|
+
# key is set in the value hash.
|
|
25
|
+
#
|
|
26
|
+
# Usage: Given a set of templates <tt>T1, T2,</tt> etc
|
|
27
|
+
#
|
|
28
|
+
# values = { "name" => "Dave", state => "TX" }
|
|
29
|
+
#
|
|
30
|
+
# t = TemplatePage.new(T1, T2, T3)
|
|
31
|
+
# File.open(name, "w") {|f| t.write_html_on(f, values)}
|
|
32
|
+
# or
|
|
33
|
+
# res = ''
|
|
34
|
+
# t.write_html_on(res, values)
|
|
35
|
+
#
|
|
36
|
+
#
|
|
37
|
+
|
|
38
|
+
class TemplatePage
|
|
39
|
+
|
|
40
|
+
##########
|
|
41
|
+
# A context holds a stack of key/value pairs (like a symbol
|
|
42
|
+
# table). When asked to resolve a key, it first searches the top of
|
|
43
|
+
# the stack, then the next level, and so on until it finds a match
|
|
44
|
+
# (or runs out of entries)
|
|
45
|
+
|
|
46
|
+
class Context
|
|
47
|
+
def initialize
|
|
48
|
+
@stack = []
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def push(hash)
|
|
52
|
+
@stack.push(hash)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def pop
|
|
56
|
+
@stack.pop
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Find a scalar value, throwing an exception if not found. This
|
|
60
|
+
# method is used when substituting the %xxx% constructs
|
|
61
|
+
|
|
62
|
+
def find_scalar(key)
|
|
63
|
+
@stack.reverse_each do |level|
|
|
64
|
+
if val = level[key]
|
|
65
|
+
return val unless val.kind_of? Array
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
raise "Template error: can't find variable '#{key}'"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Lookup any key in the stack of hashes
|
|
72
|
+
|
|
73
|
+
def lookup(key)
|
|
74
|
+
@stack.reverse_each do |level|
|
|
75
|
+
val = level[key]
|
|
76
|
+
return val if val
|
|
77
|
+
end
|
|
78
|
+
nil
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
#########
|
|
83
|
+
# Simple class to read lines out of a string
|
|
84
|
+
|
|
85
|
+
class LineReader
|
|
86
|
+
# we're initialized with an array of lines
|
|
87
|
+
def initialize(lines)
|
|
88
|
+
@lines = lines
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# read the next line
|
|
92
|
+
def read
|
|
93
|
+
@lines.shift
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Return a list of lines up to the line that matches
|
|
97
|
+
# a pattern. That last line is discarded.
|
|
98
|
+
def read_up_to(pattern)
|
|
99
|
+
res = []
|
|
100
|
+
while line = read
|
|
101
|
+
if pattern.match(line)
|
|
102
|
+
return LineReader.new(res)
|
|
103
|
+
else
|
|
104
|
+
res << line
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
raise "Missing end tag in template: #{pattern.source}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Return a copy of ourselves that can be modified without
|
|
111
|
+
# affecting us
|
|
112
|
+
def dup
|
|
113
|
+
LineReader.new(@lines.dup)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
# +templates+ is an array of strings containing the templates.
|
|
120
|
+
# We start at the first, and substitute in subsequent ones
|
|
121
|
+
# where the string <tt>!INCLUDE!</tt> occurs. For example,
|
|
122
|
+
# we could have the overall page template containing
|
|
123
|
+
#
|
|
124
|
+
# <html><body>
|
|
125
|
+
# <h1>Master</h1>
|
|
126
|
+
# !INCLUDE!
|
|
127
|
+
# </bost></html>
|
|
128
|
+
#
|
|
129
|
+
# and substitute subpages in to it by passing [master, sub_page].
|
|
130
|
+
# This gives us a cheap way of framing pages
|
|
131
|
+
|
|
132
|
+
def initialize(*templates)
|
|
133
|
+
result = "!INCLUDE!"
|
|
134
|
+
templates.each do |content|
|
|
135
|
+
result.sub!(/!INCLUDE!/, content)
|
|
136
|
+
end
|
|
137
|
+
@lines = LineReader.new(result.split($/))
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Render the templates into HTML, storing the result on +op+
|
|
141
|
+
# using the method <tt><<</tt>. The <tt>value_hash</tt> contains
|
|
142
|
+
# key/value pairs used to drive the substitution (as described above)
|
|
143
|
+
|
|
144
|
+
def write_html_on(op, value_hash)
|
|
145
|
+
@context = Context.new
|
|
146
|
+
op << substitute_into(@lines, value_hash).tr("\000", '\\')
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# Substitute a set of key/value pairs into the given template.
|
|
151
|
+
# Keys with scalar values have them substituted directly into
|
|
152
|
+
# the page. Those with array values invoke <tt>substitute_array</tt>
|
|
153
|
+
# (below), which examples a block of the template once for each
|
|
154
|
+
# row in the array.
|
|
155
|
+
#
|
|
156
|
+
# This routine also copes with the <tt>IF:</tt>_key_ directive,
|
|
157
|
+
# removing chunks of the template if the corresponding key
|
|
158
|
+
# does not appear in the hash, and the START: directive, which
|
|
159
|
+
# loops its contents for each value in an array
|
|
160
|
+
|
|
161
|
+
def substitute_into(lines, values)
|
|
162
|
+
@context.push(values)
|
|
163
|
+
skip_to = nil
|
|
164
|
+
result = []
|
|
165
|
+
|
|
166
|
+
while line = lines.read
|
|
167
|
+
|
|
168
|
+
case line
|
|
169
|
+
|
|
170
|
+
when /^IF:(\w+)/
|
|
171
|
+
lines.read_up_to(/^ENDIF:#$1/) unless @context.lookup($1)
|
|
172
|
+
|
|
173
|
+
when /^IFNOT:(\w+)/
|
|
174
|
+
lines.read_up_to(/^ENDIF:#$1/) if @context.lookup($1)
|
|
175
|
+
|
|
176
|
+
when /^ENDIF:/
|
|
177
|
+
;
|
|
178
|
+
|
|
179
|
+
when /^START:(\w+)/
|
|
180
|
+
tag = $1
|
|
181
|
+
body = lines.read_up_to(/^END:#{tag}/)
|
|
182
|
+
inner_values = @context.lookup(tag)
|
|
183
|
+
raise "unknown tag: #{tag}" unless inner_values
|
|
184
|
+
raise "not array: #{tag}" unless inner_values.kind_of?(Array)
|
|
185
|
+
inner_values.each do |vals|
|
|
186
|
+
result << substitute_into(body.dup, vals)
|
|
187
|
+
end
|
|
188
|
+
else
|
|
189
|
+
result << expand_line(line.dup)
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
@context.pop
|
|
194
|
+
|
|
195
|
+
result.join("\n")
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Given an individual line, we look for %xxx% constructs and
|
|
199
|
+
# HREF:ref:name: constructs, substituting for each.
|
|
200
|
+
|
|
201
|
+
def expand_line(line)
|
|
202
|
+
# Generate a cross reference if a reference is given,
|
|
203
|
+
# otherwise just fill in the name part
|
|
204
|
+
|
|
205
|
+
line.gsub!(/HREF:(\w+?):(\w+?):/) {
|
|
206
|
+
ref = @context.lookup($1)
|
|
207
|
+
name = @context.find_scalar($2)
|
|
208
|
+
|
|
209
|
+
if ref and !ref.kind_of?(Array)
|
|
210
|
+
"<a href=\"#{ref}\">#{name}</a>"
|
|
211
|
+
else
|
|
212
|
+
name
|
|
213
|
+
end
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
# Substitute in values for %xxx% constructs. This is made complex
|
|
217
|
+
# because the replacement string may contain characters that are
|
|
218
|
+
# meaningful to the regexp (like \1)
|
|
219
|
+
|
|
220
|
+
line = line.gsub(/%([a-zA-Z]\w*)%/) {
|
|
221
|
+
val = @context.find_scalar($1)
|
|
222
|
+
val.tr('\\', "\000")
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
line
|
|
227
|
+
rescue Exception => e
|
|
228
|
+
$stderr.puts "Error in template: #{e}"
|
|
229
|
+
$stderr.puts "Original line: #{line}"
|
|
230
|
+
exit
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
end
|
|
234
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# A TokenStream is a list of tokens, gathered during the parse
|
|
2
|
+
# of some entity (say a method). Entities populate these streams
|
|
3
|
+
# by being registered with the lexer. Any class can collect tokens
|
|
4
|
+
# by including TokenStream. From the outside, you use such an object
|
|
5
|
+
# by calling the start_collecting_tokens method, followed by calls
|
|
6
|
+
# to add_token and pop_token
|
|
7
|
+
|
|
8
|
+
module TokenStream
|
|
9
|
+
def token_stream
|
|
10
|
+
@token_stream
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def start_collecting_tokens
|
|
14
|
+
@token_stream = []
|
|
15
|
+
end
|
|
16
|
+
def add_token(tk)
|
|
17
|
+
@token_stream << tk
|
|
18
|
+
end
|
|
19
|
+
def add_tokens(tks)
|
|
20
|
+
tks.each {|tk| add_token(tk)}
|
|
21
|
+
end
|
|
22
|
+
def pop_token
|
|
23
|
+
@token_stream.pop
|
|
24
|
+
end
|
|
25
|
+
end
|