##// END OF EJS Templates
minirst: support containers...
Martin Geisler -
r10443:62d484a8 default
parent child Browse files
Show More
@@ -1,316 +1,354 b''
1 # minirst.py - minimal reStructuredText parser
1 # minirst.py - minimal reStructuredText parser
2 #
2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2009, 2010 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """simplified reStructuredText parser.
8 """simplified reStructuredText parser.
9
9
10 This parser knows just enough about reStructuredText to parse the
10 This parser knows just enough about reStructuredText to parse the
11 Mercurial docstrings.
11 Mercurial docstrings.
12
12
13 It cheats in a major way: nested blocks are not really nested. They
13 It cheats in a major way: nested blocks are not really nested. They
14 are just indented blocks that look like they are nested. This relies
14 are just indented blocks that look like they are nested. This relies
15 on the user to keep the right indentation for the blocks.
15 on the user to keep the right indentation for the blocks.
16
16
17 It only supports a small subset of reStructuredText:
17 It only supports a small subset of reStructuredText:
18
18
19 - sections
19 - sections
20
20
21 - paragraphs
21 - paragraphs
22
22
23 - literal blocks
23 - literal blocks
24
24
25 - definition lists
25 - definition lists
26
26
27 - bullet lists (items must start with '-')
27 - bullet lists (items must start with '-')
28
28
29 - enumerated lists (no autonumbering)
29 - enumerated lists (no autonumbering)
30
30
31 - field lists (colons cannot be escaped)
31 - field lists (colons cannot be escaped)
32
32
33 - option lists (supports only long options without arguments)
33 - option lists (supports only long options without arguments)
34
34
35 - inline literals (no other inline markup is not recognized)
35 - inline literals (no other inline markup is not recognized)
36 """
36 """
37
37
38 import re, sys, textwrap
38 import re, sys, textwrap
39
39
40
40
41 def findblocks(text):
41 def findblocks(text):
42 """Find continuous blocks of lines in text.
42 """Find continuous blocks of lines in text.
43
43
44 Returns a list of dictionaries representing the blocks. Each block
44 Returns a list of dictionaries representing the blocks. Each block
45 has an 'indent' field and a 'lines' field.
45 has an 'indent' field and a 'lines' field.
46 """
46 """
47 blocks = [[]]
47 blocks = [[]]
48 lines = text.splitlines()
48 lines = text.splitlines()
49 for line in lines:
49 for line in lines:
50 if line.strip():
50 if line.strip():
51 blocks[-1].append(line)
51 blocks[-1].append(line)
52 elif blocks[-1]:
52 elif blocks[-1]:
53 blocks.append([])
53 blocks.append([])
54 if not blocks[-1]:
54 if not blocks[-1]:
55 del blocks[-1]
55 del blocks[-1]
56
56
57 for i, block in enumerate(blocks):
57 for i, block in enumerate(blocks):
58 indent = min((len(l) - len(l.lstrip())) for l in block)
58 indent = min((len(l) - len(l.lstrip())) for l in block)
59 blocks[i] = dict(indent=indent, lines=[l[indent:] for l in block])
59 blocks[i] = dict(indent=indent, lines=[l[indent:] for l in block])
60 return blocks
60 return blocks
61
61
62
62
63 def findliteralblocks(blocks):
63 def findliteralblocks(blocks):
64 """Finds literal blocks and adds a 'type' field to the blocks.
64 """Finds literal blocks and adds a 'type' field to the blocks.
65
65
66 Literal blocks are given the type 'literal', all other blocks are
66 Literal blocks are given the type 'literal', all other blocks are
67 given type the 'paragraph'.
67 given type the 'paragraph'.
68 """
68 """
69 i = 0
69 i = 0
70 while i < len(blocks):
70 while i < len(blocks):
71 # Searching for a block that looks like this:
71 # Searching for a block that looks like this:
72 #
72 #
73 # +------------------------------+
73 # +------------------------------+
74 # | paragraph |
74 # | paragraph |
75 # | (ends with "::") |
75 # | (ends with "::") |
76 # +------------------------------+
76 # +------------------------------+
77 # +---------------------------+
77 # +---------------------------+
78 # | indented literal block |
78 # | indented literal block |
79 # +---------------------------+
79 # +---------------------------+
80 blocks[i]['type'] = 'paragraph'
80 blocks[i]['type'] = 'paragraph'
81 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
81 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
82 indent = blocks[i]['indent']
82 indent = blocks[i]['indent']
83 adjustment = blocks[i + 1]['indent'] - indent
83 adjustment = blocks[i + 1]['indent'] - indent
84
84
85 if blocks[i]['lines'] == ['::']:
85 if blocks[i]['lines'] == ['::']:
86 # Expanded form: remove block
86 # Expanded form: remove block
87 del blocks[i]
87 del blocks[i]
88 i -= 1
88 i -= 1
89 elif blocks[i]['lines'][-1].endswith(' ::'):
89 elif blocks[i]['lines'][-1].endswith(' ::'):
90 # Partially minimized form: remove space and both
90 # Partially minimized form: remove space and both
91 # colons.
91 # colons.
92 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
92 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
93 else:
93 else:
94 # Fully minimized form: remove just one colon.
94 # Fully minimized form: remove just one colon.
95 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
95 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
96
96
97 # List items are formatted with a hanging indent. We must
97 # List items are formatted with a hanging indent. We must
98 # correct for this here while we still have the original
98 # correct for this here while we still have the original
99 # information on the indentation of the subsequent literal
99 # information on the indentation of the subsequent literal
100 # blocks available.
100 # blocks available.
101 m = _bulletre.match(blocks[i]['lines'][0])
101 m = _bulletre.match(blocks[i]['lines'][0])
102 if m:
102 if m:
103 indent += m.end()
103 indent += m.end()
104 adjustment -= m.end()
104 adjustment -= m.end()
105
105
106 # Mark the following indented blocks.
106 # Mark the following indented blocks.
107 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
107 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
108 blocks[i + 1]['type'] = 'literal'
108 blocks[i + 1]['type'] = 'literal'
109 blocks[i + 1]['indent'] -= adjustment
109 blocks[i + 1]['indent'] -= adjustment
110 i += 1
110 i += 1
111 i += 1
111 i += 1
112 return blocks
112 return blocks
113
113
114 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)) ')
114 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)) ')
115 _optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$')
115 _optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$')
116 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
116 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
117 _definitionre = re.compile(r'[^ ]')
117 _definitionre = re.compile(r'[^ ]')
118
118
119 def splitparagraphs(blocks):
119 def splitparagraphs(blocks):
120 """Split paragraphs into lists."""
120 """Split paragraphs into lists."""
121 # Tuples with (list type, item regexp, single line items?). Order
121 # Tuples with (list type, item regexp, single line items?). Order
122 # matters: definition lists has the least specific regexp and must
122 # matters: definition lists has the least specific regexp and must
123 # come last.
123 # come last.
124 listtypes = [('bullet', _bulletre, True),
124 listtypes = [('bullet', _bulletre, True),
125 ('option', _optionre, True),
125 ('option', _optionre, True),
126 ('field', _fieldre, True),
126 ('field', _fieldre, True),
127 ('definition', _definitionre, False)]
127 ('definition', _definitionre, False)]
128
128
129 def match(lines, i, itemre, singleline):
129 def match(lines, i, itemre, singleline):
130 """Does itemre match an item at line i?
130 """Does itemre match an item at line i?
131
131
132 A list item can be followed by an idented line or another list
132 A list item can be followed by an idented line or another list
133 item (but only if singleline is True).
133 item (but only if singleline is True).
134 """
134 """
135 line1 = lines[i]
135 line1 = lines[i]
136 line2 = i + 1 < len(lines) and lines[i + 1] or ''
136 line2 = i + 1 < len(lines) and lines[i + 1] or ''
137 if not itemre.match(line1):
137 if not itemre.match(line1):
138 return False
138 return False
139 if singleline:
139 if singleline:
140 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
140 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
141 else:
141 else:
142 return line2.startswith(' ')
142 return line2.startswith(' ')
143
143
144 i = 0
144 i = 0
145 while i < len(blocks):
145 while i < len(blocks):
146 if blocks[i]['type'] == 'paragraph':
146 if blocks[i]['type'] == 'paragraph':
147 lines = blocks[i]['lines']
147 lines = blocks[i]['lines']
148 for type, itemre, singleline in listtypes:
148 for type, itemre, singleline in listtypes:
149 if match(lines, 0, itemre, singleline):
149 if match(lines, 0, itemre, singleline):
150 items = []
150 items = []
151 for j, line in enumerate(lines):
151 for j, line in enumerate(lines):
152 if match(lines, j, itemre, singleline):
152 if match(lines, j, itemre, singleline):
153 items.append(dict(type=type, lines=[],
153 items.append(dict(type=type, lines=[],
154 indent=blocks[i]['indent']))
154 indent=blocks[i]['indent']))
155 items[-1]['lines'].append(line)
155 items[-1]['lines'].append(line)
156 blocks[i:i + 1] = items
156 blocks[i:i + 1] = items
157 break
157 break
158 i += 1
158 i += 1
159 return blocks
159 return blocks
160
160
161
161
162 _fieldwidth = 12
162 _fieldwidth = 12
163
163
164 def updatefieldlists(blocks):
164 def updatefieldlists(blocks):
165 """Find key and maximum key width for field lists."""
165 """Find key and maximum key width for field lists."""
166 i = 0
166 i = 0
167 while i < len(blocks):
167 while i < len(blocks):
168 if blocks[i]['type'] != 'field':
168 if blocks[i]['type'] != 'field':
169 i += 1
169 i += 1
170 continue
170 continue
171
171
172 keywidth = 0
172 keywidth = 0
173 j = i
173 j = i
174 while j < len(blocks) and blocks[j]['type'] == 'field':
174 while j < len(blocks) and blocks[j]['type'] == 'field':
175 m = _fieldre.match(blocks[j]['lines'][0])
175 m = _fieldre.match(blocks[j]['lines'][0])
176 key, rest = m.groups()
176 key, rest = m.groups()
177 blocks[j]['lines'][0] = rest
177 blocks[j]['lines'][0] = rest
178 blocks[j]['key'] = key
178 blocks[j]['key'] = key
179 keywidth = max(keywidth, len(key))
179 keywidth = max(keywidth, len(key))
180 j += 1
180 j += 1
181
181
182 for block in blocks[i:j]:
182 for block in blocks[i:j]:
183 block['keywidth'] = keywidth
183 block['keywidth'] = keywidth
184 i = j + 1
184 i = j + 1
185
185
186 return blocks
186 return blocks
187
187
188
188
189 def prunecontainers(blocks, keep):
190 """Prune unwanted containers.
191
192 The blocks must have a 'type' field, i.e., they should have been
193 run through findliteralblocks first.
194 """
195 i = 0
196 while i + 1 < len(blocks):
197 # Searching for a block that looks like this:
198 #
199 # +-------+---------------------------+
200 # | ".. container ::" type |
201 # +---+ |
202 # | blocks |
203 # +-------------------------------+
204 if (blocks[i]['type'] == 'paragraph' and
205 blocks[i]['lines'][0].startswith('.. container::')):
206 indent = blocks[i]['indent']
207 adjustment = blocks[i + 1]['indent'] - indent
208 containertype = blocks[i]['lines'][0][15:]
209 prune = containertype not in keep
210
211 # Always delete "..container:: type" block
212 del blocks[i]
213 j = i
214 while j < len(blocks) and blocks[j]['indent'] > indent:
215 if prune:
216 del blocks[j]
217 i -= 1 # adjust outer index
218 else:
219 blocks[j]['indent'] -= adjustment
220 j += 1
221 i += 1
222 return blocks
223
224
189 def findsections(blocks):
225 def findsections(blocks):
190 """Finds sections.
226 """Finds sections.
191
227
192 The blocks must have a 'type' field, i.e., they should have been
228 The blocks must have a 'type' field, i.e., they should have been
193 run through findliteralblocks first.
229 run through findliteralblocks first.
194 """
230 """
195 for block in blocks:
231 for block in blocks:
196 # Searching for a block that looks like this:
232 # Searching for a block that looks like this:
197 #
233 #
198 # +------------------------------+
234 # +------------------------------+
199 # | Section title |
235 # | Section title |
200 # | ------------- |
236 # | ------------- |
201 # +------------------------------+
237 # +------------------------------+
202 if (block['type'] == 'paragraph' and
238 if (block['type'] == 'paragraph' and
203 len(block['lines']) == 2 and
239 len(block['lines']) == 2 and
204 block['lines'][1] == '-' * len(block['lines'][0])):
240 block['lines'][1] == '-' * len(block['lines'][0])):
205 block['type'] = 'section'
241 block['type'] = 'section'
206 return blocks
242 return blocks
207
243
208
244
209 def inlineliterals(blocks):
245 def inlineliterals(blocks):
210 for b in blocks:
246 for b in blocks:
211 if b['type'] == 'paragraph':
247 if b['type'] == 'paragraph':
212 b['lines'] = [l.replace('``', '"') for l in b['lines']]
248 b['lines'] = [l.replace('``', '"') for l in b['lines']]
213 return blocks
249 return blocks
214
250
215
251
216 def addmargins(blocks):
252 def addmargins(blocks):
217 """Adds empty blocks for vertical spacing.
253 """Adds empty blocks for vertical spacing.
218
254
219 This groups bullets, options, and definitions together with no vertical
255 This groups bullets, options, and definitions together with no vertical
220 space between them, and adds an empty block between all other blocks.
256 space between them, and adds an empty block between all other blocks.
221 """
257 """
222 i = 1
258 i = 1
223 while i < len(blocks):
259 while i < len(blocks):
224 if (blocks[i]['type'] == blocks[i - 1]['type'] and
260 if (blocks[i]['type'] == blocks[i - 1]['type'] and
225 blocks[i]['type'] in ('bullet', 'option', 'field', 'definition')):
261 blocks[i]['type'] in ('bullet', 'option', 'field', 'definition')):
226 i += 1
262 i += 1
227 else:
263 else:
228 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
264 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
229 i += 2
265 i += 2
230 return blocks
266 return blocks
231
267
232
268
233 def formatblock(block, width):
269 def formatblock(block, width):
234 """Format a block according to width."""
270 """Format a block according to width."""
235 if width <= 0:
271 if width <= 0:
236 width = 78
272 width = 78
237 indent = ' ' * block['indent']
273 indent = ' ' * block['indent']
238 if block['type'] == 'margin':
274 if block['type'] == 'margin':
239 return ''
275 return ''
240 if block['type'] == 'literal':
276 if block['type'] == 'literal':
241 indent += ' '
277 indent += ' '
242 return indent + ('\n' + indent).join(block['lines'])
278 return indent + ('\n' + indent).join(block['lines'])
243 if block['type'] == 'section':
279 if block['type'] == 'section':
244 return indent + ('\n' + indent).join(block['lines'])
280 return indent + ('\n' + indent).join(block['lines'])
245 if block['type'] == 'definition':
281 if block['type'] == 'definition':
246 term = indent + block['lines'][0]
282 term = indent + block['lines'][0]
247 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
283 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
248 defindent = indent + hang * ' '
284 defindent = indent + hang * ' '
249 text = ' '.join(map(str.strip, block['lines'][1:]))
285 text = ' '.join(map(str.strip, block['lines'][1:]))
250 return "%s\n%s" % (term, textwrap.fill(text, width=width,
286 return "%s\n%s" % (term, textwrap.fill(text, width=width,
251 initial_indent=defindent,
287 initial_indent=defindent,
252 subsequent_indent=defindent))
288 subsequent_indent=defindent))
253 initindent = subindent = indent
289 initindent = subindent = indent
254 if block['type'] == 'bullet':
290 if block['type'] == 'bullet':
255 m = _bulletre.match(block['lines'][0])
291 m = _bulletre.match(block['lines'][0])
256 subindent = indent + m.end() * ' '
292 subindent = indent + m.end() * ' '
257 elif block['type'] == 'field':
293 elif block['type'] == 'field':
258 keywidth = block['keywidth']
294 keywidth = block['keywidth']
259 key = block['key']
295 key = block['key']
260
296
261 subindent = indent + _fieldwidth * ' '
297 subindent = indent + _fieldwidth * ' '
262 if len(key) + 2 > _fieldwidth:
298 if len(key) + 2 > _fieldwidth:
263 # key too large, use full line width
299 # key too large, use full line width
264 key = key.ljust(width)
300 key = key.ljust(width)
265 elif keywidth + 2 < _fieldwidth:
301 elif keywidth + 2 < _fieldwidth:
266 # all keys are small, add only two spaces
302 # all keys are small, add only two spaces
267 key = key.ljust(keywidth + 2)
303 key = key.ljust(keywidth + 2)
268 subindent = indent + (keywidth + 2) * ' '
304 subindent = indent + (keywidth + 2) * ' '
269 else:
305 else:
270 # mixed sizes, use fieldwidth for this one
306 # mixed sizes, use fieldwidth for this one
271 key = key.ljust(_fieldwidth)
307 key = key.ljust(_fieldwidth)
272 block['lines'][0] = key + block['lines'][0]
308 block['lines'][0] = key + block['lines'][0]
273 elif block['type'] == 'option':
309 elif block['type'] == 'option':
274 m = _optionre.match(block['lines'][0])
310 m = _optionre.match(block['lines'][0])
275 option, arg, rest = m.groups()
311 option, arg, rest = m.groups()
276 subindent = indent + (len(option) + len(arg)) * ' '
312 subindent = indent + (len(option) + len(arg)) * ' '
277
313
278 text = ' '.join(map(str.strip, block['lines']))
314 text = ' '.join(map(str.strip, block['lines']))
279 return textwrap.fill(text, width=width,
315 return textwrap.fill(text, width=width,
280 initial_indent=initindent,
316 initial_indent=initindent,
281 subsequent_indent=subindent)
317 subsequent_indent=subindent)
282
318
283
319
284 def format(text, width, indent=0):
320 def format(text, width, indent=0, keep=[]):
285 """Parse and format the text according to width."""
321 """Parse and format the text according to width."""
286 blocks = findblocks(text)
322 blocks = findblocks(text)
287 for b in blocks:
323 for b in blocks:
288 b['indent'] += indent
324 b['indent'] += indent
289 blocks = findliteralblocks(blocks)
325 blocks = findliteralblocks(blocks)
326 blocks = prunecontainers(blocks, keep)
290 blocks = inlineliterals(blocks)
327 blocks = inlineliterals(blocks)
291 blocks = splitparagraphs(blocks)
328 blocks = splitparagraphs(blocks)
292 blocks = updatefieldlists(blocks)
329 blocks = updatefieldlists(blocks)
293 blocks = findsections(blocks)
330 blocks = findsections(blocks)
294 blocks = addmargins(blocks)
331 blocks = addmargins(blocks)
295 return '\n'.join(formatblock(b, width) for b in blocks)
332 return '\n'.join(formatblock(b, width) for b in blocks)
296
333
297
334
298 if __name__ == "__main__":
335 if __name__ == "__main__":
299 from pprint import pprint
336 from pprint import pprint
300
337
301 def debug(func, blocks):
338 def debug(func, *args):
302 blocks = func(blocks)
339 blocks = func(*args)
303 print "*** after %s:" % func.__name__
340 print "*** after %s:" % func.__name__
304 pprint(blocks)
341 pprint(blocks)
305 print
342 print
306 return blocks
343 return blocks
307
344
308 text = open(sys.argv[1]).read()
345 text = open(sys.argv[1]).read()
309 blocks = debug(findblocks, text)
346 blocks = debug(findblocks, text)
310 blocks = debug(findliteralblocks, blocks)
347 blocks = debug(findliteralblocks, blocks)
348 blocks = debug(prunecontainers, blocks, sys.argv[2:])
311 blocks = debug(inlineliterals, blocks)
349 blocks = debug(inlineliterals, blocks)
312 blocks = debug(splitparagraphs, blocks)
350 blocks = debug(splitparagraphs, blocks)
313 blocks = debug(updatefieldlists, blocks)
351 blocks = debug(updatefieldlists, blocks)
314 blocks = debug(findsections, blocks)
352 blocks = debug(findsections, blocks)
315 blocks = debug(addmargins, blocks)
353 blocks = debug(addmargins, blocks)
316 print '\n'.join(formatblock(b, 30) for b in blocks)
354 print '\n'.join(formatblock(b, 30) for b in blocks)
@@ -1,145 +1,167 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 from mercurial import minirst
3 from mercurial import minirst
4
4
5 def debugformat(title, text, width):
5 def debugformat(title, text, width, **kwargs):
6 print "%s formatted to fit within %d characters:" % (title, width)
6 print "%s formatted to fit within %d characters:" % (title, width)
7 print "-" * 70
7 print "-" * 70
8 print minirst.format(text, width)
8 print minirst.format(text, width, **kwargs)
9 print "-" * 70
9 print "-" * 70
10 print
10 print
11
11
12 paragraphs = """
12 paragraphs = """
13 This is some text in the first paragraph.
13 This is some text in the first paragraph.
14
14
15 A small indented paragraph.
15 A small indented paragraph.
16 It is followed by some lines
16 It is followed by some lines
17 containing random whitespace.
17 containing random whitespace.
18 \n \n \nThe third and final paragraph.
18 \n \n \nThe third and final paragraph.
19 """
19 """
20
20
21 debugformat('paragraphs', paragraphs, 60)
21 debugformat('paragraphs', paragraphs, 60)
22 debugformat('paragraphs', paragraphs, 30)
22 debugformat('paragraphs', paragraphs, 30)
23
23
24
24
25 definitions = """
25 definitions = """
26 A Term
26 A Term
27 Definition. The indented
27 Definition. The indented
28 lines make up the definition.
28 lines make up the definition.
29 Another Term
29 Another Term
30 Another definition. The final line in the
30 Another definition. The final line in the
31 definition determines the indentation, so
31 definition determines the indentation, so
32 this will be indented with four spaces.
32 this will be indented with four spaces.
33
33
34 A Nested/Indented Term
34 A Nested/Indented Term
35 Definition.
35 Definition.
36 """
36 """
37
37
38 debugformat('definitions', definitions, 60)
38 debugformat('definitions', definitions, 60)
39 debugformat('definitions', definitions, 30)
39 debugformat('definitions', definitions, 30)
40
40
41
41
42 literals = r"""
42 literals = r"""
43 The fully minimized form is the most
43 The fully minimized form is the most
44 convenient form::
44 convenient form::
45
45
46 Hello
46 Hello
47 literal
47 literal
48 world
48 world
49
49
50 In the partially minimized form a paragraph
50 In the partially minimized form a paragraph
51 simply ends with space-double-colon. ::
51 simply ends with space-double-colon. ::
52
52
53 ////////////////////////////////////////
53 ////////////////////////////////////////
54 long un-wrapped line in a literal block
54 long un-wrapped line in a literal block
55 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
55 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
56
56
57 ::
57 ::
58
58
59 This literal block is started with '::',
59 This literal block is started with '::',
60 the so-called expanded form. The paragraph
60 the so-called expanded form. The paragraph
61 with '::' disappears in the final output.
61 with '::' disappears in the final output.
62 """
62 """
63
63
64 debugformat('literals', literals, 60)
64 debugformat('literals', literals, 60)
65 debugformat('literals', literals, 30)
65 debugformat('literals', literals, 30)
66
66
67
67
68 lists = """
68 lists = """
69 - This is the first list item.
69 - This is the first list item.
70
70
71 Second paragraph in the first list item.
71 Second paragraph in the first list item.
72
72
73 - List items need not be separated
73 - List items need not be separated
74 by a blank line.
74 by a blank line.
75 - And will be rendered without
75 - And will be rendered without
76 one in any case.
76 one in any case.
77
77
78 We can have indented lists:
78 We can have indented lists:
79
79
80 - This is an indented list item
80 - This is an indented list item
81
81
82 - Another indented list item::
82 - Another indented list item::
83
83
84 - A literal block in the middle
84 - A literal block in the middle
85 of an indented list.
85 of an indented list.
86
86
87 (The above is not a list item since we are in the literal block.)
87 (The above is not a list item since we are in the literal block.)
88
88
89 ::
89 ::
90
90
91 Literal block with no indentation (apart from
91 Literal block with no indentation (apart from
92 the two spaces added to all literal blocks).
92 the two spaces added to all literal blocks).
93
93
94 1. This is an enumerated list (first item).
94 1. This is an enumerated list (first item).
95 2. Continuing with the second item.
95 2. Continuing with the second item.
96
96
97 (1) foo
97 (1) foo
98 (2) bar
98 (2) bar
99
99
100 1) Another
100 1) Another
101 2) List
101 2) List
102 """
102 """
103
103
104 debugformat('lists', lists, 60)
104 debugformat('lists', lists, 60)
105 debugformat('lists', lists, 30)
105 debugformat('lists', lists, 30)
106
106
107
107
108 options = """
108 options = """
109 There is support for simple option lists,
109 There is support for simple option lists,
110 but only with long options:
110 but only with long options:
111
111
112 --all Output all.
112 --all Output all.
113 --both Output both (this description is
113 --both Output both (this description is
114 quite long).
114 quite long).
115 --long Output all day long.
115 --long Output all day long.
116
116
117 --par This option has two paragraphs in its description.
117 --par This option has two paragraphs in its description.
118 This is the first.
118 This is the first.
119
119
120 This is the second. Blank lines may be omitted between
120 This is the second. Blank lines may be omitted between
121 options (as above) or left in (as here).
121 options (as above) or left in (as here).
122
122
123 The next paragraph looks like an option list, but lacks the two-space
123 The next paragraph looks like an option list, but lacks the two-space
124 marker after the option. It is treated as a normal paragraph:
124 marker after the option. It is treated as a normal paragraph:
125
125
126 --foo bar baz
126 --foo bar baz
127 """
127 """
128
128
129 debugformat('options', options, 60)
129 debugformat('options', options, 60)
130 debugformat('options', options, 30)
130 debugformat('options', options, 30)
131
131
132
132
133 fields = """
133 fields = """
134 :a: First item.
134 :a: First item.
135 :ab: Second item. Indentation and wrapping
135 :ab: Second item. Indentation and wrapping
136 is handled automatically.
136 is handled automatically.
137
137
138 Next list:
138 Next list:
139
139
140 :small: The larger key below triggers full indentation here.
140 :small: The larger key below triggers full indentation here.
141 :much too large: This key is big enough to get its own line.
141 :much too large: This key is big enough to get its own line.
142 """
142 """
143
143
144 debugformat('fields', fields, 60)
144 debugformat('fields', fields, 60)
145 debugformat('fields', fields, 30)
145 debugformat('fields', fields, 30)
146
147 containers = """
148 Normal output.
149
150 .. container:: debug
151
152 Initial debug output.
153
154 .. container:: verbose
155
156 Verbose output.
157
158 .. container:: debug
159
160 Debug output.
161 """
162
163 debugformat('containers (normal)', containers, 60)
164 debugformat('containers (verbose)', containers, 60, keep=['verbose'])
165 debugformat('containers (debug)', containers, 60, keep=['debug'])
166 debugformat('containers (verbose debug)', containers, 60,
167 keep=['verbose', 'debug'])
@@ -1,248 +1,278 b''
1 paragraphs formatted to fit within 60 characters:
1 paragraphs formatted to fit within 60 characters:
2 ----------------------------------------------------------------------
2 ----------------------------------------------------------------------
3 This is some text in the first paragraph.
3 This is some text in the first paragraph.
4
4
5 A small indented paragraph. It is followed by some lines
5 A small indented paragraph. It is followed by some lines
6 containing random whitespace.
6 containing random whitespace.
7
7
8 The third and final paragraph.
8 The third and final paragraph.
9 ----------------------------------------------------------------------
9 ----------------------------------------------------------------------
10
10
11 paragraphs formatted to fit within 30 characters:
11 paragraphs formatted to fit within 30 characters:
12 ----------------------------------------------------------------------
12 ----------------------------------------------------------------------
13 This is some text in the first
13 This is some text in the first
14 paragraph.
14 paragraph.
15
15
16 A small indented paragraph.
16 A small indented paragraph.
17 It is followed by some lines
17 It is followed by some lines
18 containing random
18 containing random
19 whitespace.
19 whitespace.
20
20
21 The third and final paragraph.
21 The third and final paragraph.
22 ----------------------------------------------------------------------
22 ----------------------------------------------------------------------
23
23
24 definitions formatted to fit within 60 characters:
24 definitions formatted to fit within 60 characters:
25 ----------------------------------------------------------------------
25 ----------------------------------------------------------------------
26 A Term
26 A Term
27 Definition. The indented lines make up the definition.
27 Definition. The indented lines make up the definition.
28 Another Term
28 Another Term
29 Another definition. The final line in the definition
29 Another definition. The final line in the definition
30 determines the indentation, so this will be indented
30 determines the indentation, so this will be indented
31 with four spaces.
31 with four spaces.
32 A Nested/Indented Term
32 A Nested/Indented Term
33 Definition.
33 Definition.
34 ----------------------------------------------------------------------
34 ----------------------------------------------------------------------
35
35
36 definitions formatted to fit within 30 characters:
36 definitions formatted to fit within 30 characters:
37 ----------------------------------------------------------------------
37 ----------------------------------------------------------------------
38 A Term
38 A Term
39 Definition. The indented
39 Definition. The indented
40 lines make up the
40 lines make up the
41 definition.
41 definition.
42 Another Term
42 Another Term
43 Another definition. The
43 Another definition. The
44 final line in the
44 final line in the
45 definition determines the
45 definition determines the
46 indentation, so this will
46 indentation, so this will
47 be indented with four
47 be indented with four
48 spaces.
48 spaces.
49 A Nested/Indented Term
49 A Nested/Indented Term
50 Definition.
50 Definition.
51 ----------------------------------------------------------------------
51 ----------------------------------------------------------------------
52
52
53 literals formatted to fit within 60 characters:
53 literals formatted to fit within 60 characters:
54 ----------------------------------------------------------------------
54 ----------------------------------------------------------------------
55 The fully minimized form is the most convenient form:
55 The fully minimized form is the most convenient form:
56
56
57 Hello
57 Hello
58 literal
58 literal
59 world
59 world
60
60
61 In the partially minimized form a paragraph simply ends with
61 In the partially minimized form a paragraph simply ends with
62 space-double-colon.
62 space-double-colon.
63
63
64 ////////////////////////////////////////
64 ////////////////////////////////////////
65 long un-wrapped line in a literal block
65 long un-wrapped line in a literal block
66 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
66 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
67
67
68 This literal block is started with '::',
68 This literal block is started with '::',
69 the so-called expanded form. The paragraph
69 the so-called expanded form. The paragraph
70 with '::' disappears in the final output.
70 with '::' disappears in the final output.
71 ----------------------------------------------------------------------
71 ----------------------------------------------------------------------
72
72
73 literals formatted to fit within 30 characters:
73 literals formatted to fit within 30 characters:
74 ----------------------------------------------------------------------
74 ----------------------------------------------------------------------
75 The fully minimized form is
75 The fully minimized form is
76 the most convenient form:
76 the most convenient form:
77
77
78 Hello
78 Hello
79 literal
79 literal
80 world
80 world
81
81
82 In the partially minimized
82 In the partially minimized
83 form a paragraph simply ends
83 form a paragraph simply ends
84 with space-double-colon.
84 with space-double-colon.
85
85
86 ////////////////////////////////////////
86 ////////////////////////////////////////
87 long un-wrapped line in a literal block
87 long un-wrapped line in a literal block
88 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
88 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
89
89
90 This literal block is started with '::',
90 This literal block is started with '::',
91 the so-called expanded form. The paragraph
91 the so-called expanded form. The paragraph
92 with '::' disappears in the final output.
92 with '::' disappears in the final output.
93 ----------------------------------------------------------------------
93 ----------------------------------------------------------------------
94
94
95 lists formatted to fit within 60 characters:
95 lists formatted to fit within 60 characters:
96 ----------------------------------------------------------------------
96 ----------------------------------------------------------------------
97 - This is the first list item.
97 - This is the first list item.
98
98
99 Second paragraph in the first list item.
99 Second paragraph in the first list item.
100
100
101 - List items need not be separated by a blank line.
101 - List items need not be separated by a blank line.
102 - And will be rendered without one in any case.
102 - And will be rendered without one in any case.
103
103
104 We can have indented lists:
104 We can have indented lists:
105
105
106 - This is an indented list item
106 - This is an indented list item
107 - Another indented list item:
107 - Another indented list item:
108
108
109 - A literal block in the middle
109 - A literal block in the middle
110 of an indented list.
110 of an indented list.
111
111
112 (The above is not a list item since we are in the literal block.)
112 (The above is not a list item since we are in the literal block.)
113
113
114 Literal block with no indentation (apart from
114 Literal block with no indentation (apart from
115 the two spaces added to all literal blocks).
115 the two spaces added to all literal blocks).
116
116
117 1. This is an enumerated list (first item).
117 1. This is an enumerated list (first item).
118 2. Continuing with the second item.
118 2. Continuing with the second item.
119 (1) foo
119 (1) foo
120 (2) bar
120 (2) bar
121 1) Another
121 1) Another
122 2) List
122 2) List
123 ----------------------------------------------------------------------
123 ----------------------------------------------------------------------
124
124
125 lists formatted to fit within 30 characters:
125 lists formatted to fit within 30 characters:
126 ----------------------------------------------------------------------
126 ----------------------------------------------------------------------
127 - This is the first list item.
127 - This is the first list item.
128
128
129 Second paragraph in the
129 Second paragraph in the
130 first list item.
130 first list item.
131
131
132 - List items need not be
132 - List items need not be
133 separated by a blank line.
133 separated by a blank line.
134 - And will be rendered without
134 - And will be rendered without
135 one in any case.
135 one in any case.
136
136
137 We can have indented lists:
137 We can have indented lists:
138
138
139 - This is an indented list
139 - This is an indented list
140 item
140 item
141 - Another indented list
141 - Another indented list
142 item:
142 item:
143
143
144 - A literal block in the middle
144 - A literal block in the middle
145 of an indented list.
145 of an indented list.
146
146
147 (The above is not a list item since we are in the literal block.)
147 (The above is not a list item since we are in the literal block.)
148
148
149 Literal block with no indentation (apart from
149 Literal block with no indentation (apart from
150 the two spaces added to all literal blocks).
150 the two spaces added to all literal blocks).
151
151
152 1. This is an enumerated list
152 1. This is an enumerated list
153 (first item).
153 (first item).
154 2. Continuing with the second
154 2. Continuing with the second
155 item.
155 item.
156 (1) foo
156 (1) foo
157 (2) bar
157 (2) bar
158 1) Another
158 1) Another
159 2) List
159 2) List
160 ----------------------------------------------------------------------
160 ----------------------------------------------------------------------
161
161
162 options formatted to fit within 60 characters:
162 options formatted to fit within 60 characters:
163 ----------------------------------------------------------------------
163 ----------------------------------------------------------------------
164 There is support for simple option lists, but only with long
164 There is support for simple option lists, but only with long
165 options:
165 options:
166
166
167 --all Output all.
167 --all Output all.
168 --both Output both (this description is quite long).
168 --both Output both (this description is quite long).
169 --long Output all day long.
169 --long Output all day long.
170 --par This option has two paragraphs in its
170 --par This option has two paragraphs in its
171 description. This is the first.
171 description. This is the first.
172
172
173 This is the second. Blank lines may be omitted
173 This is the second. Blank lines may be omitted
174 between options (as above) or left in (as here).
174 between options (as above) or left in (as here).
175
175
176 The next paragraph looks like an option list, but lacks the
176 The next paragraph looks like an option list, but lacks the
177 two-space marker after the option. It is treated as a normal
177 two-space marker after the option. It is treated as a normal
178 paragraph:
178 paragraph:
179
179
180 --foo bar baz
180 --foo bar baz
181 ----------------------------------------------------------------------
181 ----------------------------------------------------------------------
182
182
183 options formatted to fit within 30 characters:
183 options formatted to fit within 30 characters:
184 ----------------------------------------------------------------------
184 ----------------------------------------------------------------------
185 There is support for simple
185 There is support for simple
186 option lists, but only with
186 option lists, but only with
187 long options:
187 long options:
188
188
189 --all Output all.
189 --all Output all.
190 --both Output both (this
190 --both Output both (this
191 description is
191 description is
192 quite long).
192 quite long).
193 --long Output all day
193 --long Output all day
194 long.
194 long.
195 --par This option has two
195 --par This option has two
196 paragraphs in its
196 paragraphs in its
197 description. This
197 description. This
198 is the first.
198 is the first.
199
199
200 This is the second.
200 This is the second.
201 Blank lines may be
201 Blank lines may be
202 omitted between
202 omitted between
203 options (as above)
203 options (as above)
204 or left in (as
204 or left in (as
205 here).
205 here).
206
206
207 The next paragraph looks like
207 The next paragraph looks like
208 an option list, but lacks the
208 an option list, but lacks the
209 two-space marker after the
209 two-space marker after the
210 option. It is treated as a
210 option. It is treated as a
211 normal paragraph:
211 normal paragraph:
212
212
213 --foo bar baz
213 --foo bar baz
214 ----------------------------------------------------------------------
214 ----------------------------------------------------------------------
215
215
216 fields formatted to fit within 60 characters:
216 fields formatted to fit within 60 characters:
217 ----------------------------------------------------------------------
217 ----------------------------------------------------------------------
218 a First item.
218 a First item.
219 ab Second item. Indentation and wrapping is handled
219 ab Second item. Indentation and wrapping is handled
220 automatically.
220 automatically.
221
221
222 Next list:
222 Next list:
223
223
224 small The larger key below triggers full indentation
224 small The larger key below triggers full indentation
225 here.
225 here.
226 much too large
226 much too large
227 This key is big enough to get its own line.
227 This key is big enough to get its own line.
228 ----------------------------------------------------------------------
228 ----------------------------------------------------------------------
229
229
230 fields formatted to fit within 30 characters:
230 fields formatted to fit within 30 characters:
231 ----------------------------------------------------------------------
231 ----------------------------------------------------------------------
232 a First item.
232 a First item.
233 ab Second item. Indentation
233 ab Second item. Indentation
234 and wrapping is handled
234 and wrapping is handled
235 automatically.
235 automatically.
236
236
237 Next list:
237 Next list:
238
238
239 small The larger key
239 small The larger key
240 below triggers
240 below triggers
241 full indentation
241 full indentation
242 here.
242 here.
243 much too large
243 much too large
244 This key is big
244 This key is big
245 enough to get its
245 enough to get its
246 own line.
246 own line.
247 ----------------------------------------------------------------------
247 ----------------------------------------------------------------------
248
248
249 containers (normal) formatted to fit within 60 characters:
250 ----------------------------------------------------------------------
251 Normal output.
252 ----------------------------------------------------------------------
253
254 containers (verbose) formatted to fit within 60 characters:
255 ----------------------------------------------------------------------
256 Normal output.
257
258 Verbose output.
259 ----------------------------------------------------------------------
260
261 containers (debug) formatted to fit within 60 characters:
262 ----------------------------------------------------------------------
263 Normal output.
264
265 Initial debug output.
266 ----------------------------------------------------------------------
267
268 containers (verbose debug) formatted to fit within 60 characters:
269 ----------------------------------------------------------------------
270 Normal output.
271
272 Initial debug output.
273
274 Verbose output.
275
276 Debug output.
277 ----------------------------------------------------------------------
278
General Comments 0
You need to be logged in to leave comments. Login now