sqlpostgres 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
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,474 @@
1
+ # = Introduction
2
+ #
3
+ # SimpleMarkup parses plain text documents and attempts to decompose
4
+ # them into their constituent parts. Some of these parts are high-level:
5
+ # paragraphs, chunks of verbatim text, list entries and the like. Other
6
+ # parts happen at the character level: a piece of bold text, a word in
7
+ # code font. This markup is similar in spirit to that used on WikiWiki
8
+ # webs, where folks create web pages using a simple set of formatting
9
+ # rules.
10
+ #
11
+ # SimpleMarkup itself does no output formatting: this is left to a
12
+ # different set of classes.
13
+ #
14
+ # SimpleMarkup is extendable at runtime: you can add new markup
15
+ # elements to be recognised in the documents that SimpleMarkup parses.
16
+ #
17
+ # SimpleMarkup is intended to be the basis for a family of tools which
18
+ # share the common requirement that simple, plain-text should be
19
+ # rendered in a variety of different output formats and media. It is
20
+ # envisaged that SimpleMarkup could be the basis for formating RDoc
21
+ # style comment blocks, Wiki entries, and online FAQs.
22
+ #
23
+ # = Basic Formatting
24
+ #
25
+ # * SimpleMarkup looks for a document's natural left margin. This is
26
+ # used as the initial margin for the document.
27
+ #
28
+ # * Consecutive lines starting at this margin are considered to be a
29
+ # paragraph.
30
+ #
31
+ # * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
32
+ # taken to be the start of a list. The margin in increased to be the
33
+ # first non-space following the list start flag. Subsequent lines
34
+ # should be indented to this new margin until the list ends. For
35
+ # example:
36
+ #
37
+ # * this is a list with three paragraphs in
38
+ # the first item. This is the first paragraph.
39
+ #
40
+ # And this is the second paragraph.
41
+ #
42
+ # 1. This is an indented, numbered list.
43
+ # 2. This is the second item in that list
44
+ #
45
+ # This is the third conventional paragraph in the
46
+ # first list item.
47
+ #
48
+ # * This is the second item in the original list
49
+ #
50
+ # * You can also construct labeled lists, sometimes called description
51
+ # or definition lists. Do this by putting the label in square brackets
52
+ # and indenting the list body:
53
+ #
54
+ # [cat] a small furry mammal
55
+ # that seems to sleep a lot
56
+ #
57
+ # [ant] a little insect that is known
58
+ # to enjoy picnics
59
+ #
60
+ # A minor variation on labeled lists uses two colons to separate the
61
+ # label from the list body:
62
+ #
63
+ # cat:: a small furry mammal
64
+ # that seems to sleep a lot
65
+ #
66
+ # ant:: a little insect that is known
67
+ # to enjoy picnics
68
+ #
69
+ # This latter style guarantees that the list bodies' left margins are
70
+ # aligned: think of them as a two column table.
71
+ #
72
+ # * Any line that starts to the right of the current margin is treated
73
+ # as verbatim text. This is useful for code listings. The example of a
74
+ # list above is also verbatim text.
75
+ #
76
+ # * A line starting with an equals sign (=) is treated as a
77
+ # heading. Level one headings have one equals sign, level two headings
78
+ # have two,and so on.
79
+ #
80
+ # * A line starting with three or more hyphens (at the current indent)
81
+ # generates a horizontal rule. THe more hyphens, the thicker the rule
82
+ # (within reason, and if supported by the output device)
83
+ #
84
+ # * You can use markup within text (except verbatim) to change the
85
+ # appearance of parts of that text. Out of the box, SimpleMarkup
86
+ # supports word-based and general markup.
87
+ #
88
+ # Word-based markup uses flag characters around individual words:
89
+ #
90
+ # [\*word*] displays word in a *bold* font
91
+ # [\_word_] displays word in an _emphasized_ font
92
+ # [\+word+] displays word in a +code+ font
93
+ #
94
+ # General markup affects text between a start delimiter and and end
95
+ # delimiter. Not surprisingly, these delimiters look like HTML markup.
96
+ #
97
+ # [\<b>text...</b>] displays word in a *bold* font
98
+ # [\<em>text...</em>] displays word in an _emphasized_ font
99
+ # [\<i>text...</i>] displays word in an _emphasized_ font
100
+ # [\<tt>text...</tt>] displays word in a +code+ font
101
+ #
102
+ # Unlike conventional Wiki markup, general markup can cross line
103
+ # boundaries. You can turn off the interpretation of markup by
104
+ # preceding the first character with a backslash, so \\\<b>bold
105
+ # text</b> and \\\*bold* produce \<b>bold text</b> and \*bold
106
+ # respectively.
107
+ #
108
+ # = Using SimpleMarkup
109
+ #
110
+ # For information on using SimpleMarkup programatically,
111
+ # see SM::SimpleMarkup.
112
+ #
113
+ # Author:: Dave Thomas, dave@pragmaticprogrammer.com
114
+ # Version:: 0.0
115
+ # License:: Ruby license
116
+
117
+
118
+
119
+ require 'markup/simple_markup/fragments'
120
+ require 'markup/simple_markup/lines.rb'
121
+
122
+ module SM #:nodoc:
123
+
124
+ # == Synopsis
125
+ #
126
+ # This code converts <tt>input_string</tt>, which is in the format
127
+ # described in markup/simple_markup.rb, to HTML. The conversion
128
+ # takes place in the +convert+ method, so you can use the same
129
+ # SimpleMarkup object to convert multiple input strings.
130
+ #
131
+ # require 'markup/simple_markup'
132
+ # require 'markup/simple_markup/to_html'
133
+ #
134
+ # p = SM::SimpleMarkup.new
135
+ # h = SM::ToHtml.new
136
+ #
137
+ # puts p.convert(input_string, h)
138
+ #
139
+ # You can extend the SimpleMarkup parser to recognise new markup
140
+ # sequences, and to add special processing for text that matches a
141
+ # regular epxression. Here we make WikiWords significant to the parser,
142
+ # and also make the sequences {word} and \<no>text...</no> signify
143
+ # strike-through text. When then subclass the HTML output class to deal
144
+ # with these:
145
+ #
146
+ # require 'markup/simple_markup'
147
+ # require 'markup/simple_markup/to_html'
148
+ #
149
+ # class WikiHtml < SM::ToHtml
150
+ # def handle_special_WIKIWORD(special)
151
+ # "<font color=red>" + special.text + "</font>"
152
+ # end
153
+ # end
154
+ #
155
+ # p = SM::SimpleMarkup.new
156
+ # p.add_word_pair("{", "}", :STRIKE)
157
+ # p.add_html("no", :STRIKE)
158
+ #
159
+ # p.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
160
+ #
161
+ # h = WikiHtml.new
162
+ # h.add_tag(:STRIKE, "<strike>", "</strike>")
163
+ #
164
+ # puts "<body>" + p.convert(ARGF.read, h) + "</body>"
165
+ #
166
+ # == Output Formatters
167
+ #
168
+ # _missing_
169
+ #
170
+ #
171
+
172
+ class SimpleMarkup
173
+
174
+ SPACE = ?\s
175
+
176
+ # List entries look like:
177
+ # * text
178
+ # 1. text
179
+ # [label] text
180
+ # label:: text
181
+ #
182
+ # Flag it as a list entry, and
183
+ # work out the indent for subsequent lines
184
+
185
+ SIMPLE_LIST_RE = /^(
186
+ ( \* (?# bullet)
187
+ |- (?# bullet)
188
+ |\d+\. (?# numbered )
189
+ )
190
+ \s+
191
+ )\S/x
192
+
193
+ LABEL_LIST_RE = /^(
194
+ ( \[.*?\] (?# labeled )
195
+ |\S.*:: (?# note )
196
+ )(?=\s|$)
197
+ \s*
198
+ )/x
199
+
200
+
201
+ ##
202
+ # take a block of text and use various heuristics to determine
203
+ # it's structure (paragraphs, lists, and so on). Invoke an
204
+ # event handler as we identify significant chunks.
205
+ #
206
+
207
+ def initialize
208
+ @am = AttributeManager.new
209
+ @output = nil
210
+ end
211
+
212
+ ##
213
+ # Add to the sequences used to add formatting to an individual word
214
+ # (such as *bold*). Matching entries will generate attibutes
215
+ # that the output formatters can recognize by their +name+
216
+
217
+ def add_word_pair(start, stop, name)
218
+ @am.add_word_pair(start, stop, name)
219
+ end
220
+
221
+ ##
222
+ # Add to the sequences recognized as general markup
223
+ #
224
+
225
+ def add_html(tag, name)
226
+ @am.add_html(tag, name)
227
+ end
228
+
229
+ ##
230
+ # Add to other inline sequences. For example, we could add
231
+ # WikiWords using something like:
232
+ #
233
+ # parser.add_special(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
234
+ #
235
+ # Each wiki word will be presented to the output formatter
236
+ # via the accept_special method
237
+ #
238
+
239
+ def add_special(pattern, name)
240
+ @am.add_special(pattern, name)
241
+ end
242
+
243
+
244
+ # We take a string, split it into lines, work out the type of
245
+ # each line, and from there deduce groups of lines (for example
246
+ # all lines in a paragraph). We then invoke the output formatter
247
+ # using a Visitor to display the result
248
+
249
+ def convert(str, op)
250
+ @lines = Lines.new(str.split(/\r?\n/).collect { |aLine|
251
+ Line.new(aLine) })
252
+ return "" if @lines.empty?
253
+ @lines.normalize
254
+ assign_types_to_lines
255
+ group = group_lines
256
+ # call the output formatter to handle the result
257
+ # group.to_a.each {|i| p i}
258
+ group.accept(@am, op)
259
+ end
260
+
261
+
262
+ #######
263
+ private
264
+ #######
265
+
266
+
267
+ ##
268
+ # Look through the text at line indentation. We flag each line as being
269
+ # Blank, a paragraph, a list element, or verbatim text
270
+ #
271
+
272
+ def assign_types_to_lines(margin = 0, level = 0)
273
+
274
+ while line = @lines.next
275
+ if line.isBlank?
276
+ line.stamp(Line::BLANK, level)
277
+ next
278
+ end
279
+
280
+ # if a line contains non-blanks before the margin, then it must belong
281
+ # to an outer level
282
+
283
+ text = line.text
284
+
285
+ for i in 0...margin
286
+ if text[i] != SPACE
287
+ @lines.unget
288
+ return
289
+ end
290
+ end
291
+
292
+ active_line = text[margin..-1]
293
+
294
+ # Rules (horizontal lines) look like
295
+ #
296
+ # --- (three or more hyphens)
297
+ #
298
+ # The more hyphens, the thicker the rule
299
+ #
300
+
301
+ if /^(---+)\s*$/ =~ active_line
302
+ line.stamp(Line::RULE, level, $1.length-2)
303
+ next
304
+ end
305
+
306
+ # Then look for list entries. First the ones that have to have
307
+ # text following them (* xxx, - xxx, and dd. xxx)
308
+
309
+ if SIMPLE_LIST_RE =~ active_line
310
+
311
+ offset = margin + $1.length
312
+ prefix = $2
313
+ prefix_length = prefix.length
314
+
315
+ flag = case prefix
316
+ when "*","-" then ListBase::BULLET
317
+ when /^\d/ then ListBase::NUMBER
318
+ else raise "Invalid List Type: #{self.inspect}"
319
+ end
320
+
321
+ line.stamp(Line::LIST, level+1, prefix, flag)
322
+ text[margin, prefix_length] = " " * prefix_length
323
+ assign_types_to_lines(offset, level + 1)
324
+ next
325
+ end
326
+
327
+
328
+ if LABEL_LIST_RE =~ active_line
329
+ offset = margin + $1.length
330
+ prefix = $2
331
+ prefix_length = prefix.length
332
+
333
+ next if handled_labeled_list(line, level, margin, offset, prefix)
334
+ end
335
+
336
+ # Headings look like
337
+ # = Main heading
338
+ # == Second level
339
+ # === Third
340
+ #
341
+ # Headings reset the level to 0
342
+
343
+ if active_line[0] == ?= and active_line =~ /^(=+)\s*(.*)/
344
+ prefix_length = $1.length
345
+ prefix_length = 6 if prefix_length > 6
346
+ line.stamp(Line::HEADING, 0, prefix_length)
347
+ line.strip_leading(margin + prefix_length)
348
+ next
349
+ end
350
+
351
+ # If the character's a space, then we have verbatim text,
352
+ # otherwise
353
+
354
+ if active_line[0] == SPACE
355
+ line.strip_leading(margin) if margin > 0
356
+ line.stamp(Line::VERBATIM, level)
357
+ else
358
+ line.stamp(Line::PARAGRAPH, level)
359
+ end
360
+ end
361
+ end
362
+
363
+ # Handle labeled list entries, We have a special case
364
+ # to deal with. Because the labels can be long, they force
365
+ # the remaining block of text over the to right:
366
+ #
367
+ # this is a long label that I wrote:: and here is the
368
+ # block of text with
369
+ # a silly margin
370
+ #
371
+ # So we allow the special case. If the label is followed
372
+ # by nothing, and if the following line is indented, then
373
+ # we take the indent of that line as the new margin
374
+ #
375
+ # this is a long label that I wrote::
376
+ # here is a more reasonably indented block which
377
+ # will ab attached to the label.
378
+ #
379
+
380
+ def handled_labeled_list(line, level, margin, offset, prefix)
381
+ prefix_length = prefix.length
382
+ text = line.text
383
+ flag = nil
384
+ case prefix
385
+ when /^\[/
386
+ flag = ListBase::LABELED
387
+ prefix = prefix[1, prefix.length-2]
388
+ when /:$/
389
+ flag = ListBase::NOTE
390
+ prefix.chop!
391
+ else raise "Invalid List Type: #{self.inspect}"
392
+ end
393
+
394
+ # body is on the next line
395
+
396
+ if text.length <= offset
397
+ original_line = line
398
+ line = @lines.next
399
+ return(false) unless line
400
+ text = line.text
401
+
402
+ for i in 0..margin
403
+ if text[i] != SPACE
404
+ @lines.unget
405
+ return false
406
+ end
407
+ end
408
+ i = margin
409
+ i += 1 while text[i] == SPACE
410
+ if i >= text.length
411
+ @lines.unget
412
+ return false
413
+ else
414
+ offset = i
415
+ prefix_length = 0
416
+ @lines.delete(original_line)
417
+ end
418
+ end
419
+
420
+ line.stamp(Line::LIST, level+1, prefix, flag)
421
+ text[margin, prefix_length] = " " * prefix_length
422
+ assign_types_to_lines(offset, level + 1)
423
+ return true
424
+ end
425
+
426
+ # Return a block consisting of fragments which are
427
+ # paragraphs, list entries or verbatim text. We merge consecutive
428
+ # lines of the same type and level together. We are also slightly
429
+ # tricky with lists: the lines following a list introduction
430
+ # look like paragraph lines at the next level, and we remap them
431
+ # into list entries instead
432
+
433
+ def group_lines
434
+ @lines.rewind
435
+
436
+ inList = false
437
+ wantedType = wantedLevel = nil
438
+
439
+ block = LineCollection.new
440
+ group = nil
441
+
442
+ while line = @lines.next
443
+ if line.level == wantedLevel and line.type == wantedType
444
+ group.add_text(line.text)
445
+ else
446
+ group = block.fragment_for(line)
447
+ block.add(group)
448
+ if line.type == Line::LIST
449
+ wantedType = Line::PARAGRAPH
450
+ else
451
+ wantedType = line.type
452
+ end
453
+ wantedLevel = line.level
454
+ end
455
+ end
456
+
457
+ block.normalize
458
+ block
459
+ end
460
+
461
+ ## for debugging, we allow access to our line contents as text
462
+ def content
463
+ @lines.as_text
464
+ end
465
+ public :content
466
+
467
+ ## for debugging, return the list of line types
468
+ def get_line_types
469
+ @lines.line_types
470
+ end
471
+ public :get_line_types
472
+ end
473
+
474
+ end
@@ -0,0 +1,2 @@
1
+ require 'TestParse.rb'
2
+ require 'TestInline.rb'
@@ -0,0 +1,151 @@
1
+ require "rubyunit"
2
+
3
+ $:.unshift "../.."
4
+
5
+ require "markup/simple_markup/inline"
6
+
7
+ class TestInline < TestCase
8
+
9
+
10
+ def setup
11
+ @am = SM::AttributeManager.new
12
+
13
+ @bold_on = @am.changed_attribute_by_name([], [:BOLD])
14
+ @bold_off = @am.changed_attribute_by_name([:BOLD], [])
15
+
16
+ @tt_on = @am.changed_attribute_by_name([], [:TT])
17
+ @tt_off = @am.changed_attribute_by_name([:TT], [])
18
+
19
+ @em_on = @am.changed_attribute_by_name([], [:EM])
20
+ @em_off = @am.changed_attribute_by_name([:EM], [])
21
+
22
+ @bold_em_on = @am.changed_attribute_by_name([], [:BOLD] | [:EM])
23
+ @bold_em_off = @am.changed_attribute_by_name([:BOLD] | [:EM], [])
24
+
25
+ @em_then_bold = @am.changed_attribute_by_name([:EM], [:EM] | [:BOLD])
26
+
27
+ @em_to_bold = @am.changed_attribute_by_name([:EM], [:BOLD])
28
+
29
+ @am.add_word_pair("{", "}", :WOMBAT)
30
+ @wombat_on = @am.changed_attribute_by_name([], [:WOMBAT])
31
+ @wombat_off = @am.changed_attribute_by_name([:WOMBAT], [])
32
+ end
33
+
34
+ def crossref(text)
35
+ [ @am.changed_attribute_by_name([], [:CROSSREF] | [:_SPECIAL_]),
36
+ SM::Special.new(33, text),
37
+ @am.changed_attribute_by_name([:CROSSREF] | [:_SPECIAL_], [])
38
+ ]
39
+ end
40
+
41
+ def test_special
42
+ # class names, variable names, file names, or instance variables
43
+ @am.add_special(/(
44
+ \b([A-Z]\w+(::\w+)*)
45
+ | \#\w+[!?=]?
46
+ | \b\w+([_\/\.]+\w+)+[!?=]?
47
+ )/x,
48
+ :CROSSREF)
49
+
50
+ assert_equals(["cat"], @am.flow("cat"))
51
+
52
+ assert_equals(["cat ", crossref("#fred"), " dog"].flatten,
53
+ @am.flow("cat #fred dog"))
54
+
55
+ assert_equals([crossref("#fred"), " dog"].flatten,
56
+ @am.flow("#fred dog"))
57
+
58
+ assert_equals(["cat ", crossref("#fred")].flatten, @am.flow("cat #fred"))
59
+ end
60
+
61
+ def test_basic
62
+ assert_equals(["cat"], @am.flow("cat"))
63
+
64
+ assert_equals(["cat ", @bold_on, "and", @bold_off, " dog"],
65
+ @am.flow("cat *and* dog"))
66
+
67
+ assert_equals(["cat ", @bold_on, "AND", @bold_off, " dog"],
68
+ @am.flow("cat *AND* dog"))
69
+
70
+ assert_equals(["cat ", @em_on, "And", @em_off, " dog"],
71
+ @am.flow("cat _And_ dog"))
72
+
73
+ assert_equals(["cat *and dog*"], @am.flow("cat *and dog*"))
74
+
75
+ assert_equals(["*cat and* dog"], @am.flow("*cat and* dog"))
76
+
77
+ assert_equals(["cat *and ", @bold_on, "dog", @bold_off],
78
+ @am.flow("cat *and *dog*"))
79
+
80
+ assert_equals(["cat ", @em_on, "and", @em_off, " dog"],
81
+ @am.flow("cat _and_ dog"))
82
+
83
+ assert_equals(["cat_and_dog"],
84
+ @am.flow("cat_and_dog"))
85
+
86
+ assert_equals(["cat ", @tt_on, "and", @tt_off, " dog"],
87
+ @am.flow("cat +and+ dog"))
88
+
89
+ assert_equals(["cat ", @bold_on, "a_b_c", @bold_off, " dog"],
90
+ @am.flow("cat *a_b_c* dog"))
91
+
92
+ assert_equals(["cat __ dog"],
93
+ @am.flow("cat __ dog"))
94
+
95
+ assert_equals(["cat ", @em_on, "_", @em_off, " dog"],
96
+ @am.flow("cat ___ dog"))
97
+
98
+ end
99
+
100
+ def test_combined
101
+ assert_equals(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
102
+ @am.flow("cat _and_ *dog*"))
103
+
104
+ assert_equals(["cat ", @em_on, "a__nd", @em_off, " ", @bold_on, "dog", @bold_off],
105
+ @am.flow("cat _a__nd_ *dog*"))
106
+ end
107
+
108
+ def test_html_like
109
+ assert_equals(["cat ", @tt_on, "dog", @tt_off], @am.flow("cat <tt>dog</Tt>"))
110
+
111
+ assert_equals(["cat ", @em_on, "and", @em_off, " ", @bold_on, "dog", @bold_off],
112
+ @am.flow("cat <i>and</i> <B>dog</b>"))
113
+
114
+ assert_equals(["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off],
115
+ @am.flow("cat <i>and <B>dog</B></I>"))
116
+
117
+ assert_equals(["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
118
+ @am.flow("cat <i>and </i><b>dog</b>"))
119
+
120
+ assert_equals(["cat ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
121
+ @am.flow("cat <i>and <b></i>dog</b>"))
122
+
123
+ assert_equals([@tt_on, "cat", @tt_off, " ", @em_on, "and ", @em_to_bold, "dog", @bold_off],
124
+ @am.flow("<tt>cat</tt> <i>and <b></i>dog</b>"))
125
+
126
+ assert_equals(["cat ", @em_on, "and ", @em_then_bold, "dog", @bold_em_off],
127
+ @am.flow("cat <i>and <b>dog</b></i>"))
128
+
129
+ assert_equals(["cat ", @bold_em_on, "and", @bold_em_off, " dog"],
130
+ @am.flow("cat <i><b>and</b></i> dog"))
131
+
132
+
133
+ end
134
+
135
+ def test_protect
136
+ assert_equals(['cat \\ dog'], @am.flow('cat \\ dog'))
137
+
138
+ assert_equals(["cat <tt>dog</Tt>"], @am.flow("cat \\<tt>dog</Tt>"))
139
+
140
+ assert_equals(["cat ", @em_on, "and", @em_off, " <B>dog</b>"],
141
+ @am.flow("cat <i>and</i> \\<B>dog</b>"))
142
+
143
+ assert_equals(["*word* or <b>text</b>"], @am.flow("\\*word* or \\<b>text</b>"))
144
+ end
145
+
146
+ def test_adding
147
+ assert_equals(["cat ", @wombat_on, "and", @wombat_off, " dog" ],
148
+ @am.flow("cat {and} dog"))
149
+ assert_equals(["cat {and} dog" ], @am.flow("cat \\{and} dog"))
150
+ end
151
+ end