##// END OF EJS Templates
minirst: add basic HTML formatting support
Matt Mackall -
r15261:e2df5b86 default
parent child Browse files
Show More
@@ -1,579 +1,666 b''
1 # minirst.py - minimal reStructuredText parser
1 # minirst.py - minimal reStructuredText parser
2 #
2 #
3 # Copyright 2009, 2010 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 Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
17 Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
18 when adding support for new constructs.
18 when adding support for new constructs.
19 """
19 """
20
20
21 import re
21 import re
22 import util, encoding
22 import util, encoding
23 from i18n import _
23 from i18n import _
24
24
25 def replace(text, substs):
25 def replace(text, substs):
26 for f, t in substs:
26 for f, t in substs:
27 text = text.replace(f, t)
27 text = text.replace(f, t)
28 return text
28 return text
29
29
30 _blockre = re.compile(r"\n(?:\s*\n)+")
30 _blockre = re.compile(r"\n(?:\s*\n)+")
31
31
32 def findblocks(text):
32 def findblocks(text):
33 """Find continuous blocks of lines in text.
33 """Find continuous blocks of lines in text.
34
34
35 Returns a list of dictionaries representing the blocks. Each block
35 Returns a list of dictionaries representing the blocks. Each block
36 has an 'indent' field and a 'lines' field.
36 has an 'indent' field and a 'lines' field.
37 """
37 """
38 blocks = []
38 blocks = []
39 for b in _blockre.split(text.lstrip('\n').rstrip()):
39 for b in _blockre.split(text.lstrip('\n').rstrip()):
40 lines = b.splitlines()
40 lines = b.splitlines()
41 if lines:
41 if lines:
42 indent = min((len(l) - len(l.lstrip())) for l in lines)
42 indent = min((len(l) - len(l.lstrip())) for l in lines)
43 lines = [l[indent:] for l in lines]
43 lines = [l[indent:] for l in lines]
44 blocks.append(dict(indent=indent, lines=lines))
44 blocks.append(dict(indent=indent, lines=lines))
45 return blocks
45 return blocks
46
46
47 def findliteralblocks(blocks):
47 def findliteralblocks(blocks):
48 """Finds literal blocks and adds a 'type' field to the blocks.
48 """Finds literal blocks and adds a 'type' field to the blocks.
49
49
50 Literal blocks are given the type 'literal', all other blocks are
50 Literal blocks are given the type 'literal', all other blocks are
51 given type the 'paragraph'.
51 given type the 'paragraph'.
52 """
52 """
53 i = 0
53 i = 0
54 while i < len(blocks):
54 while i < len(blocks):
55 # Searching for a block that looks like this:
55 # Searching for a block that looks like this:
56 #
56 #
57 # +------------------------------+
57 # +------------------------------+
58 # | paragraph |
58 # | paragraph |
59 # | (ends with "::") |
59 # | (ends with "::") |
60 # +------------------------------+
60 # +------------------------------+
61 # +---------------------------+
61 # +---------------------------+
62 # | indented literal block |
62 # | indented literal block |
63 # +---------------------------+
63 # +---------------------------+
64 blocks[i]['type'] = 'paragraph'
64 blocks[i]['type'] = 'paragraph'
65 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
65 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
66 indent = blocks[i]['indent']
66 indent = blocks[i]['indent']
67 adjustment = blocks[i + 1]['indent'] - indent
67 adjustment = blocks[i + 1]['indent'] - indent
68
68
69 if blocks[i]['lines'] == ['::']:
69 if blocks[i]['lines'] == ['::']:
70 # Expanded form: remove block
70 # Expanded form: remove block
71 del blocks[i]
71 del blocks[i]
72 i -= 1
72 i -= 1
73 elif blocks[i]['lines'][-1].endswith(' ::'):
73 elif blocks[i]['lines'][-1].endswith(' ::'):
74 # Partially minimized form: remove space and both
74 # Partially minimized form: remove space and both
75 # colons.
75 # colons.
76 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
76 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
77 else:
77 else:
78 # Fully minimized form: remove just one colon.
78 # Fully minimized form: remove just one colon.
79 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
79 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
80
80
81 # List items are formatted with a hanging indent. We must
81 # List items are formatted with a hanging indent. We must
82 # correct for this here while we still have the original
82 # correct for this here while we still have the original
83 # information on the indentation of the subsequent literal
83 # information on the indentation of the subsequent literal
84 # blocks available.
84 # blocks available.
85 m = _bulletre.match(blocks[i]['lines'][0])
85 m = _bulletre.match(blocks[i]['lines'][0])
86 if m:
86 if m:
87 indent += m.end()
87 indent += m.end()
88 adjustment -= m.end()
88 adjustment -= m.end()
89
89
90 # Mark the following indented blocks.
90 # Mark the following indented blocks.
91 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
91 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
92 blocks[i + 1]['type'] = 'literal'
92 blocks[i + 1]['type'] = 'literal'
93 blocks[i + 1]['indent'] -= adjustment
93 blocks[i + 1]['indent'] -= adjustment
94 i += 1
94 i += 1
95 i += 1
95 i += 1
96 return blocks
96 return blocks
97
97
98 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
98 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
99 _optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
99 _optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
100 r'((.*) +)(.*)$')
100 r'((.*) +)(.*)$')
101 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
101 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
102 _definitionre = re.compile(r'[^ ]')
102 _definitionre = re.compile(r'[^ ]')
103 _tablere = re.compile(r'(=+\s+)*=+')
103 _tablere = re.compile(r'(=+\s+)*=+')
104
104
105 def splitparagraphs(blocks):
105 def splitparagraphs(blocks):
106 """Split paragraphs into lists."""
106 """Split paragraphs into lists."""
107 # Tuples with (list type, item regexp, single line items?). Order
107 # Tuples with (list type, item regexp, single line items?). Order
108 # matters: definition lists has the least specific regexp and must
108 # matters: definition lists has the least specific regexp and must
109 # come last.
109 # come last.
110 listtypes = [('bullet', _bulletre, True),
110 listtypes = [('bullet', _bulletre, True),
111 ('option', _optionre, True),
111 ('option', _optionre, True),
112 ('field', _fieldre, True),
112 ('field', _fieldre, True),
113 ('definition', _definitionre, False)]
113 ('definition', _definitionre, False)]
114
114
115 def match(lines, i, itemre, singleline):
115 def match(lines, i, itemre, singleline):
116 """Does itemre match an item at line i?
116 """Does itemre match an item at line i?
117
117
118 A list item can be followed by an idented line or another list
118 A list item can be followed by an idented line or another list
119 item (but only if singleline is True).
119 item (but only if singleline is True).
120 """
120 """
121 line1 = lines[i]
121 line1 = lines[i]
122 line2 = i + 1 < len(lines) and lines[i + 1] or ''
122 line2 = i + 1 < len(lines) and lines[i + 1] or ''
123 if not itemre.match(line1):
123 if not itemre.match(line1):
124 return False
124 return False
125 if singleline:
125 if singleline:
126 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
126 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
127 else:
127 else:
128 return line2.startswith(' ')
128 return line2.startswith(' ')
129
129
130 i = 0
130 i = 0
131 while i < len(blocks):
131 while i < len(blocks):
132 if blocks[i]['type'] == 'paragraph':
132 if blocks[i]['type'] == 'paragraph':
133 lines = blocks[i]['lines']
133 lines = blocks[i]['lines']
134 for type, itemre, singleline in listtypes:
134 for type, itemre, singleline in listtypes:
135 if match(lines, 0, itemre, singleline):
135 if match(lines, 0, itemre, singleline):
136 items = []
136 items = []
137 for j, line in enumerate(lines):
137 for j, line in enumerate(lines):
138 if match(lines, j, itemre, singleline):
138 if match(lines, j, itemre, singleline):
139 items.append(dict(type=type, lines=[],
139 items.append(dict(type=type, lines=[],
140 indent=blocks[i]['indent']))
140 indent=blocks[i]['indent']))
141 items[-1]['lines'].append(line)
141 items[-1]['lines'].append(line)
142 blocks[i:i + 1] = items
142 blocks[i:i + 1] = items
143 break
143 break
144 i += 1
144 i += 1
145 return blocks
145 return blocks
146
146
147 _fieldwidth = 12
147 _fieldwidth = 12
148
148
149 def updatefieldlists(blocks):
149 def updatefieldlists(blocks):
150 """Find key and maximum key width for field lists."""
150 """Find key and maximum key width for field lists."""
151 i = 0
151 i = 0
152 while i < len(blocks):
152 while i < len(blocks):
153 if blocks[i]['type'] != 'field':
153 if blocks[i]['type'] != 'field':
154 i += 1
154 i += 1
155 continue
155 continue
156
156
157 keywidth = 0
157 keywidth = 0
158 j = i
158 j = i
159 while j < len(blocks) and blocks[j]['type'] == 'field':
159 while j < len(blocks) and blocks[j]['type'] == 'field':
160 m = _fieldre.match(blocks[j]['lines'][0])
160 m = _fieldre.match(blocks[j]['lines'][0])
161 key, rest = m.groups()
161 key, rest = m.groups()
162 blocks[j]['lines'][0] = rest
162 blocks[j]['lines'][0] = rest
163 blocks[j]['key'] = key
163 blocks[j]['key'] = key
164 keywidth = max(keywidth, len(key))
164 keywidth = max(keywidth, len(key))
165 j += 1
165 j += 1
166
166
167 for block in blocks[i:j]:
167 for block in blocks[i:j]:
168 block['keywidth'] = keywidth
168 block['keywidth'] = keywidth
169 i = j + 1
169 i = j + 1
170
170
171 return blocks
171 return blocks
172
172
173 def updateoptionlists(blocks):
173 def updateoptionlists(blocks):
174 i = 0
174 i = 0
175 while i < len(blocks):
175 while i < len(blocks):
176 if blocks[i]['type'] != 'option':
176 if blocks[i]['type'] != 'option':
177 i += 1
177 i += 1
178 continue
178 continue
179
179
180 optstrwidth = 0
180 optstrwidth = 0
181 j = i
181 j = i
182 while j < len(blocks) and blocks[j]['type'] == 'option':
182 while j < len(blocks) and blocks[j]['type'] == 'option':
183 m = _optionre.match(blocks[j]['lines'][0])
183 m = _optionre.match(blocks[j]['lines'][0])
184
184
185 shortoption = m.group(2)
185 shortoption = m.group(2)
186 group3 = m.group(3)
186 group3 = m.group(3)
187 longoption = group3[2:].strip()
187 longoption = group3[2:].strip()
188 desc = m.group(6).strip()
188 desc = m.group(6).strip()
189 longoptionarg = m.group(5).strip()
189 longoptionarg = m.group(5).strip()
190 blocks[j]['lines'][0] = desc
190 blocks[j]['lines'][0] = desc
191
191
192 noshortop = ''
192 noshortop = ''
193 if not shortoption:
193 if not shortoption:
194 noshortop = ' '
194 noshortop = ' '
195
195
196 opt = "%s%s" % (shortoption and "-%s " % shortoption or '',
196 opt = "%s%s" % (shortoption and "-%s " % shortoption or '',
197 ("%s--%s %s") % (noshortop, longoption,
197 ("%s--%s %s") % (noshortop, longoption,
198 longoptionarg))
198 longoptionarg))
199 opt = opt.rstrip()
199 opt = opt.rstrip()
200 blocks[j]['optstr'] = opt
200 blocks[j]['optstr'] = opt
201 optstrwidth = max(optstrwidth, encoding.colwidth(opt))
201 optstrwidth = max(optstrwidth, encoding.colwidth(opt))
202 j += 1
202 j += 1
203
203
204 for block in blocks[i:j]:
204 for block in blocks[i:j]:
205 block['optstrwidth'] = optstrwidth
205 block['optstrwidth'] = optstrwidth
206 i = j + 1
206 i = j + 1
207 return blocks
207 return blocks
208
208
209 def prunecontainers(blocks, keep):
209 def prunecontainers(blocks, keep):
210 """Prune unwanted containers.
210 """Prune unwanted containers.
211
211
212 The blocks must have a 'type' field, i.e., they should have been
212 The blocks must have a 'type' field, i.e., they should have been
213 run through findliteralblocks first.
213 run through findliteralblocks first.
214 """
214 """
215 pruned = []
215 pruned = []
216 i = 0
216 i = 0
217 while i + 1 < len(blocks):
217 while i + 1 < len(blocks):
218 # Searching for a block that looks like this:
218 # Searching for a block that looks like this:
219 #
219 #
220 # +-------+---------------------------+
220 # +-------+---------------------------+
221 # | ".. container ::" type |
221 # | ".. container ::" type |
222 # +---+ |
222 # +---+ |
223 # | blocks |
223 # | blocks |
224 # +-------------------------------+
224 # +-------------------------------+
225 if (blocks[i]['type'] == 'paragraph' and
225 if (blocks[i]['type'] == 'paragraph' and
226 blocks[i]['lines'][0].startswith('.. container::')):
226 blocks[i]['lines'][0].startswith('.. container::')):
227 indent = blocks[i]['indent']
227 indent = blocks[i]['indent']
228 adjustment = blocks[i + 1]['indent'] - indent
228 adjustment = blocks[i + 1]['indent'] - indent
229 containertype = blocks[i]['lines'][0][15:]
229 containertype = blocks[i]['lines'][0][15:]
230 prune = containertype not in keep
230 prune = containertype not in keep
231 if prune:
231 if prune:
232 pruned.append(containertype)
232 pruned.append(containertype)
233
233
234 # Always delete "..container:: type" block
234 # Always delete "..container:: type" block
235 del blocks[i]
235 del blocks[i]
236 j = i
236 j = i
237 i -= 1
237 i -= 1
238 while j < len(blocks) and blocks[j]['indent'] > indent:
238 while j < len(blocks) and blocks[j]['indent'] > indent:
239 if prune:
239 if prune:
240 del blocks[j]
240 del blocks[j]
241 else:
241 else:
242 blocks[j]['indent'] -= adjustment
242 blocks[j]['indent'] -= adjustment
243 j += 1
243 j += 1
244 i += 1
244 i += 1
245 return blocks, pruned
245 return blocks, pruned
246
246
247 _sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
247 _sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
248
248
249 def findtables(blocks):
249 def findtables(blocks):
250 '''Find simple tables
250 '''Find simple tables
251
251
252 Only simple one-line table elements are supported
252 Only simple one-line table elements are supported
253 '''
253 '''
254
254
255 for block in blocks:
255 for block in blocks:
256 # Searching for a block that looks like this:
256 # Searching for a block that looks like this:
257 #
257 #
258 # === ==== ===
258 # === ==== ===
259 # A B C
259 # A B C
260 # === ==== === <- optional
260 # === ==== === <- optional
261 # 1 2 3
261 # 1 2 3
262 # x y z
262 # x y z
263 # === ==== ===
263 # === ==== ===
264 if (block['type'] == 'paragraph' and
264 if (block['type'] == 'paragraph' and
265 len(block['lines']) > 2 and
265 len(block['lines']) > 2 and
266 _tablere.match(block['lines'][0]) and
266 _tablere.match(block['lines'][0]) and
267 block['lines'][0] == block['lines'][-1]):
267 block['lines'][0] == block['lines'][-1]):
268 block['type'] = 'table'
268 block['type'] = 'table'
269 block['header'] = False
269 block['header'] = False
270 div = block['lines'][0]
270 div = block['lines'][0]
271
271
272 # column markers are ASCII so we can calculate column
272 # column markers are ASCII so we can calculate column
273 # position in bytes
273 # position in bytes
274 columns = [x for x in xrange(len(div))
274 columns = [x for x in xrange(len(div))
275 if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
275 if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
276 rows = []
276 rows = []
277 for l in block['lines'][1:-1]:
277 for l in block['lines'][1:-1]:
278 if l == div:
278 if l == div:
279 block['header'] = True
279 block['header'] = True
280 continue
280 continue
281 row = []
281 row = []
282 # we measure columns not in bytes or characters but in
282 # we measure columns not in bytes or characters but in
283 # colwidth which makes things tricky
283 # colwidth which makes things tricky
284 pos = columns[0] # leading whitespace is bytes
284 pos = columns[0] # leading whitespace is bytes
285 for n, start in enumerate(columns):
285 for n, start in enumerate(columns):
286 if n + 1 < len(columns):
286 if n + 1 < len(columns):
287 width = columns[n + 1] - start
287 width = columns[n + 1] - start
288 v = encoding.getcols(l, pos, width) # gather columns
288 v = encoding.getcols(l, pos, width) # gather columns
289 pos += len(v) # calculate byte position of end
289 pos += len(v) # calculate byte position of end
290 row.append(v.strip())
290 row.append(v.strip())
291 else:
291 else:
292 row.append(l[pos:].strip())
292 row.append(l[pos:].strip())
293 rows.append(row)
293 rows.append(row)
294
294
295 block['table'] = rows
295 block['table'] = rows
296
296
297 return blocks
297 return blocks
298
298
299 def findsections(blocks):
299 def findsections(blocks):
300 """Finds sections.
300 """Finds sections.
301
301
302 The blocks must have a 'type' field, i.e., they should have been
302 The blocks must have a 'type' field, i.e., they should have been
303 run through findliteralblocks first.
303 run through findliteralblocks first.
304 """
304 """
305 for block in blocks:
305 for block in blocks:
306 # Searching for a block that looks like this:
306 # Searching for a block that looks like this:
307 #
307 #
308 # +------------------------------+
308 # +------------------------------+
309 # | Section title |
309 # | Section title |
310 # | ------------- |
310 # | ------------- |
311 # +------------------------------+
311 # +------------------------------+
312 if (block['type'] == 'paragraph' and
312 if (block['type'] == 'paragraph' and
313 len(block['lines']) == 2 and
313 len(block['lines']) == 2 and
314 encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
314 encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
315 _sectionre.match(block['lines'][1])):
315 _sectionre.match(block['lines'][1])):
316 block['underline'] = block['lines'][1][0]
316 block['underline'] = block['lines'][1][0]
317 block['type'] = 'section'
317 block['type'] = 'section'
318 del block['lines'][1]
318 del block['lines'][1]
319 return blocks
319 return blocks
320
320
321 def inlineliterals(blocks):
321 def inlineliterals(blocks):
322 substs = [('``', '"')]
322 substs = [('``', '"')]
323 for b in blocks:
323 for b in blocks:
324 if b['type'] in ('paragraph', 'section'):
324 if b['type'] in ('paragraph', 'section'):
325 b['lines'] = [replace(l, substs) for l in b['lines']]
325 b['lines'] = [replace(l, substs) for l in b['lines']]
326 return blocks
326 return blocks
327
327
328 def hgrole(blocks):
328 def hgrole(blocks):
329 substs = [(':hg:`', '"hg '), ('`', '"')]
329 substs = [(':hg:`', '"hg '), ('`', '"')]
330 for b in blocks:
330 for b in blocks:
331 if b['type'] in ('paragraph', 'section'):
331 if b['type'] in ('paragraph', 'section'):
332 # Turn :hg:`command` into "hg command". This also works
332 # Turn :hg:`command` into "hg command". This also works
333 # when there is a line break in the command and relies on
333 # when there is a line break in the command and relies on
334 # the fact that we have no stray back-quotes in the input
334 # the fact that we have no stray back-quotes in the input
335 # (run the blocks through inlineliterals first).
335 # (run the blocks through inlineliterals first).
336 b['lines'] = [replace(l, substs) for l in b['lines']]
336 b['lines'] = [replace(l, substs) for l in b['lines']]
337 return blocks
337 return blocks
338
338
339 def addmargins(blocks):
339 def addmargins(blocks):
340 """Adds empty blocks for vertical spacing.
340 """Adds empty blocks for vertical spacing.
341
341
342 This groups bullets, options, and definitions together with no vertical
342 This groups bullets, options, and definitions together with no vertical
343 space between them, and adds an empty block between all other blocks.
343 space between them, and adds an empty block between all other blocks.
344 """
344 """
345 i = 1
345 i = 1
346 while i < len(blocks):
346 while i < len(blocks):
347 if (blocks[i]['type'] == blocks[i - 1]['type'] and
347 if (blocks[i]['type'] == blocks[i - 1]['type'] and
348 blocks[i]['type'] in ('bullet', 'option', 'field')):
348 blocks[i]['type'] in ('bullet', 'option', 'field')):
349 i += 1
349 i += 1
350 else:
350 else:
351 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
351 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
352 i += 2
352 i += 2
353 return blocks
353 return blocks
354
354
355 def prunecomments(blocks):
355 def prunecomments(blocks):
356 """Remove comments."""
356 """Remove comments."""
357 i = 0
357 i = 0
358 while i < len(blocks):
358 while i < len(blocks):
359 b = blocks[i]
359 b = blocks[i]
360 if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
360 if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
361 b['lines'] == ['..']):
361 b['lines'] == ['..']):
362 del blocks[i]
362 del blocks[i]
363 if i < len(blocks) and blocks[i]['type'] == 'margin':
363 if i < len(blocks) and blocks[i]['type'] == 'margin':
364 del blocks[i]
364 del blocks[i]
365 else:
365 else:
366 i += 1
366 i += 1
367 return blocks
367 return blocks
368
368
369 _admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
369 _admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
370 r"error|hint|important|note|tip|warning)::",
370 r"error|hint|important|note|tip|warning)::",
371 flags=re.IGNORECASE)
371 flags=re.IGNORECASE)
372
372
373 def findadmonitions(blocks):
373 def findadmonitions(blocks):
374 """
374 """
375 Makes the type of the block an admonition block if
375 Makes the type of the block an admonition block if
376 the first line is an admonition directive
376 the first line is an admonition directive
377 """
377 """
378 i = 0
378 i = 0
379 while i < len(blocks):
379 while i < len(blocks):
380 m = _admonitionre.match(blocks[i]['lines'][0])
380 m = _admonitionre.match(blocks[i]['lines'][0])
381 if m:
381 if m:
382 blocks[i]['type'] = 'admonition'
382 blocks[i]['type'] = 'admonition'
383 admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
383 admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
384
384
385 firstline = blocks[i]['lines'][0][m.end() + 1:]
385 firstline = blocks[i]['lines'][0][m.end() + 1:]
386 if firstline:
386 if firstline:
387 blocks[i]['lines'].insert(1, ' ' + firstline)
387 blocks[i]['lines'].insert(1, ' ' + firstline)
388
388
389 blocks[i]['admonitiontitle'] = admonitiontitle
389 blocks[i]['admonitiontitle'] = admonitiontitle
390 del blocks[i]['lines'][0]
390 del blocks[i]['lines'][0]
391 i = i + 1
391 i = i + 1
392 return blocks
392 return blocks
393
393
394 _admonitiontitles = {'attention': _('Attention:'),
394 _admonitiontitles = {'attention': _('Attention:'),
395 'caution': _('Caution:'),
395 'caution': _('Caution:'),
396 'danger': _('!Danger!') ,
396 'danger': _('!Danger!') ,
397 'error': _('Error:'),
397 'error': _('Error:'),
398 'hint': _('Hint:'),
398 'hint': _('Hint:'),
399 'important': _('Important:'),
399 'important': _('Important:'),
400 'note': _('Note:'),
400 'note': _('Note:'),
401 'tip': _('Tip:'),
401 'tip': _('Tip:'),
402 'warning': _('Warning!')}
402 'warning': _('Warning!')}
403
403
404 def formatoption(block, width):
404 def formatoption(block, width):
405 desc = ' '.join(map(str.strip, block['lines']))
405 desc = ' '.join(map(str.strip, block['lines']))
406 colwidth = encoding.colwidth(block['optstr'])
406 colwidth = encoding.colwidth(block['optstr'])
407 usablewidth = width - 1
407 usablewidth = width - 1
408 hanging = block['optstrwidth']
408 hanging = block['optstrwidth']
409 initindent = '%s%s ' % (block['optstr'], ' ' * ((hanging - colwidth)))
409 initindent = '%s%s ' % (block['optstr'], ' ' * ((hanging - colwidth)))
410 hangindent = ' ' * (encoding.colwidth(initindent) + 1)
410 hangindent = ' ' * (encoding.colwidth(initindent) + 1)
411 return ' %s\n' % (util.wrap(desc, usablewidth,
411 return ' %s\n' % (util.wrap(desc, usablewidth,
412 initindent=initindent,
412 initindent=initindent,
413 hangindent=hangindent))
413 hangindent=hangindent))
414
414
415 def formatblock(block, width):
415 def formatblock(block, width):
416 """Format a block according to width."""
416 """Format a block according to width."""
417 if width <= 0:
417 if width <= 0:
418 width = 78
418 width = 78
419 indent = ' ' * block['indent']
419 indent = ' ' * block['indent']
420 if block['type'] == 'admonition':
420 if block['type'] == 'admonition':
421 admonition = _admonitiontitles[block['admonitiontitle']]
421 admonition = _admonitiontitles[block['admonitiontitle']]
422 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
422 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
423
423
424 defindent = indent + hang * ' '
424 defindent = indent + hang * ' '
425 text = ' '.join(map(str.strip, block['lines']))
425 text = ' '.join(map(str.strip, block['lines']))
426 return '%s\n%s\n' % (indent + admonition,
426 return '%s\n%s\n' % (indent + admonition,
427 util.wrap(text, width=width,
427 util.wrap(text, width=width,
428 initindent=defindent,
428 initindent=defindent,
429 hangindent=defindent))
429 hangindent=defindent))
430 if block['type'] == 'margin':
430 if block['type'] == 'margin':
431 return '\n'
431 return '\n'
432 if block['type'] == 'literal':
432 if block['type'] == 'literal':
433 indent += ' '
433 indent += ' '
434 return indent + ('\n' + indent).join(block['lines']) + '\n'
434 return indent + ('\n' + indent).join(block['lines']) + '\n'
435 if block['type'] == 'section':
435 if block['type'] == 'section':
436 underline = encoding.colwidth(block['lines'][0]) * block['underline']
436 underline = encoding.colwidth(block['lines'][0]) * block['underline']
437 return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
437 return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
438 if block['type'] == 'table':
438 if block['type'] == 'table':
439 table = block['table']
439 table = block['table']
440 # compute column widths
440 # compute column widths
441 widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
441 widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
442 text = ''
442 text = ''
443 span = sum(widths) + len(widths) - 1
443 span = sum(widths) + len(widths) - 1
444 indent = ' ' * block['indent']
444 indent = ' ' * block['indent']
445 hang = ' ' * (len(indent) + span - widths[-1])
445 hang = ' ' * (len(indent) + span - widths[-1])
446
446
447 for row in table:
447 for row in table:
448 l = []
448 l = []
449 for w, v in zip(widths, row):
449 for w, v in zip(widths, row):
450 pad = ' ' * (w - encoding.colwidth(v))
450 pad = ' ' * (w - encoding.colwidth(v))
451 l.append(v + pad)
451 l.append(v + pad)
452 l = ' '.join(l)
452 l = ' '.join(l)
453 l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
453 l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
454 if not text and block['header']:
454 if not text and block['header']:
455 text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
455 text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
456 else:
456 else:
457 text += l + "\n"
457 text += l + "\n"
458 return text
458 return text
459 if block['type'] == 'definition':
459 if block['type'] == 'definition':
460 term = indent + block['lines'][0]
460 term = indent + block['lines'][0]
461 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
461 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
462 defindent = indent + hang * ' '
462 defindent = indent + hang * ' '
463 text = ' '.join(map(str.strip, block['lines'][1:]))
463 text = ' '.join(map(str.strip, block['lines'][1:]))
464 return '%s\n%s\n' % (term, util.wrap(text, width=width,
464 return '%s\n%s\n' % (term, util.wrap(text, width=width,
465 initindent=defindent,
465 initindent=defindent,
466 hangindent=defindent))
466 hangindent=defindent))
467 subindent = indent
467 subindent = indent
468 if block['type'] == 'bullet':
468 if block['type'] == 'bullet':
469 if block['lines'][0].startswith('| '):
469 if block['lines'][0].startswith('| '):
470 # Remove bullet for line blocks and add no extra
470 # Remove bullet for line blocks and add no extra
471 # indention.
471 # indention.
472 block['lines'][0] = block['lines'][0][2:]
472 block['lines'][0] = block['lines'][0][2:]
473 else:
473 else:
474 m = _bulletre.match(block['lines'][0])
474 m = _bulletre.match(block['lines'][0])
475 subindent = indent + m.end() * ' '
475 subindent = indent + m.end() * ' '
476 elif block['type'] == 'field':
476 elif block['type'] == 'field':
477 keywidth = block['keywidth']
477 keywidth = block['keywidth']
478 key = block['key']
478 key = block['key']
479
479
480 subindent = indent + _fieldwidth * ' '
480 subindent = indent + _fieldwidth * ' '
481 if len(key) + 2 > _fieldwidth:
481 if len(key) + 2 > _fieldwidth:
482 # key too large, use full line width
482 # key too large, use full line width
483 key = key.ljust(width)
483 key = key.ljust(width)
484 elif keywidth + 2 < _fieldwidth:
484 elif keywidth + 2 < _fieldwidth:
485 # all keys are small, add only two spaces
485 # all keys are small, add only two spaces
486 key = key.ljust(keywidth + 2)
486 key = key.ljust(keywidth + 2)
487 subindent = indent + (keywidth + 2) * ' '
487 subindent = indent + (keywidth + 2) * ' '
488 else:
488 else:
489 # mixed sizes, use fieldwidth for this one
489 # mixed sizes, use fieldwidth for this one
490 key = key.ljust(_fieldwidth)
490 key = key.ljust(_fieldwidth)
491 block['lines'][0] = key + block['lines'][0]
491 block['lines'][0] = key + block['lines'][0]
492 elif block['type'] == 'option':
492 elif block['type'] == 'option':
493 return formatoption(block, width)
493 return formatoption(block, width)
494
494
495 text = ' '.join(map(str.strip, block['lines']))
495 text = ' '.join(map(str.strip, block['lines']))
496 return util.wrap(text, width=width,
496 return util.wrap(text, width=width,
497 initindent=indent,
497 initindent=indent,
498 hangindent=subindent) + '\n'
498 hangindent=subindent) + '\n'
499
499
500 def formathtml(blocks):
501 """Format RST blocks as HTML"""
502
503 out = []
504 headernest = ''
505 listnest = []
506
507 def openlist(start, level):
508 if not listnest or listnest[-1][0] != start:
509 listnest.append((start, level))
510 out.append('<%s>\n' % start)
511
512 blocks = [b for b in blocks if b['type'] != 'margin']
513
514 for pos, b in enumerate(blocks):
515 btype = b['type']
516 level = b['indent']
517 lines = b['lines']
518
519 if btype == 'admonition':
520 admonition = _admonitiontitles[b['admonitiontitle']]
521 text = ' '.join(map(str.strip, lines))
522 out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
523 elif btype == 'paragraph':
524 out.append('<p>\n%s\n</p>\n' % '\n'.join(lines))
525 elif btype == 'margin':
526 pass
527 elif btype == 'literal':
528 out.append('<pre>\n%s\n</pre>\n' % '\n'.join(lines))
529 elif btype == 'section':
530 i = b['underline']
531 if i not in headernest:
532 headernest += i
533 level = headernest.index(i) + 1
534 out.append('<h%d>%s</h%d>\n' % (level, lines[0], level))
535 elif btype == 'table':
536 table = b['table']
537 t = []
538 for row in table:
539 l = []
540 for v in zip(row):
541 if not t:
542 l.append('<th>%s</th>' % v)
543 else:
544 l.append('<td>%s</td>' % v)
545 t.append(' <tr>%s</tr>\n' % ''.join(l))
546 out.append('<table>\n%s</table>\n' % ''.join(t))
547 elif btype == 'definition':
548 openlist('dl', level)
549 term = lines[0]
550 text = ' '.join(map(str.strip, lines[1:]))
551 out.append(' <dt>%s\n <dd>%s\n' % (term, text))
552 elif btype == 'bullet':
553 bullet, head = lines[0].split(' ', 1)
554 if bullet == '-':
555 openlist('ul', level)
556 else:
557 openlist('ol', level)
558 out.append(' <li> %s\n' % ' '.join([head] + lines[1:]))
559 elif btype == 'field':
560 openlist('dl', level)
561 key = b['key']
562 text = ' '.join(map(str.strip, lines))
563 out.append(' <dt>%s\n <dd>%s\n' % (key, text))
564 elif btype == 'option':
565 openlist('dl', level)
566 opt = b['optstr']
567 desc = ' '.join(map(str.strip, lines))
568 out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
569
570 # close lists if indent level of next block is lower
571 if listnest:
572 start, level = listnest[-1]
573 if pos == len(blocks) - 1:
574 out.append('</%s>\n' % start)
575 listnest.pop()
576 else:
577 nb = blocks[pos + 1]
578 ni = nb['indent']
579 if (ni < level or
580 (ni == level and
581 nb['type'] not in 'definition bullet field option')):
582 out.append('</%s>\n' % start)
583 listnest.pop()
584
585 return ''.join(out)
586
500 def parse(text, indent=0, keep=None):
587 def parse(text, indent=0, keep=None):
501 """Parse text into a list of blocks"""
588 """Parse text into a list of blocks"""
502 pruned = []
589 pruned = []
503 blocks = findblocks(text)
590 blocks = findblocks(text)
504 for b in blocks:
591 for b in blocks:
505 b['indent'] += indent
592 b['indent'] += indent
506 blocks = findliteralblocks(blocks)
593 blocks = findliteralblocks(blocks)
507 blocks = findtables(blocks)
594 blocks = findtables(blocks)
508 blocks, pruned = prunecontainers(blocks, keep or [])
595 blocks, pruned = prunecontainers(blocks, keep or [])
509 blocks = findsections(blocks)
596 blocks = findsections(blocks)
510 blocks = inlineliterals(blocks)
597 blocks = inlineliterals(blocks)
511 blocks = hgrole(blocks)
598 blocks = hgrole(blocks)
512 blocks = splitparagraphs(blocks)
599 blocks = splitparagraphs(blocks)
513 blocks = updatefieldlists(blocks)
600 blocks = updatefieldlists(blocks)
514 blocks = updateoptionlists(blocks)
601 blocks = updateoptionlists(blocks)
515 blocks = addmargins(blocks)
602 blocks = addmargins(blocks)
516 blocks = prunecomments(blocks)
603 blocks = prunecomments(blocks)
517 blocks = findadmonitions(blocks)
604 blocks = findadmonitions(blocks)
518 return blocks, pruned
605 return blocks, pruned
519
606
520 def formatblocks(blocks, width):
607 def formatblocks(blocks, width):
521 text = ''.join(formatblock(b, width) for b in blocks)
608 text = ''.join(formatblock(b, width) for b in blocks)
522 return text
609 return text
523
610
524 def format(text, width, indent=0, keep=None):
611 def format(text, width, indent=0, keep=None):
525 """Parse and format the text according to width."""
612 """Parse and format the text according to width."""
526 blocks, pruned = parse(text, indent, keep or [])
613 blocks, pruned = parse(text, indent, keep or [])
527 text = ''.join(formatblock(b, width) for b in blocks)
614 text = ''.join(formatblock(b, width) for b in blocks)
528 if keep is None:
615 if keep is None:
529 return text
616 return text
530 else:
617 else:
531 return text, pruned
618 return text, pruned
532
619
533 def getsections(blocks):
620 def getsections(blocks):
534 '''return a list of (section name, nesting level, blocks) tuples'''
621 '''return a list of (section name, nesting level, blocks) tuples'''
535 nest = ""
622 nest = ""
536 level = 0
623 level = 0
537 secs = []
624 secs = []
538 for b in blocks:
625 for b in blocks:
539 if b['type'] == 'section':
626 if b['type'] == 'section':
540 i = b['underline']
627 i = b['underline']
541 if i not in nest:
628 if i not in nest:
542 nest += i
629 nest += i
543 level = nest.index(i) + 1
630 level = nest.index(i) + 1
544 nest = nest[:level]
631 nest = nest[:level]
545 secs.append((b['lines'][0], level, [b]))
632 secs.append((b['lines'][0], level, [b]))
546 else:
633 else:
547 if not secs:
634 if not secs:
548 # add an initial empty section
635 # add an initial empty section
549 secs = [('', 0, [])]
636 secs = [('', 0, [])]
550 secs[-1][2].append(b)
637 secs[-1][2].append(b)
551 return secs
638 return secs
552
639
553 def decorateblocks(blocks, width):
640 def decorateblocks(blocks, width):
554 '''generate a list of (section name, line text) pairs for search'''
641 '''generate a list of (section name, line text) pairs for search'''
555 lines = []
642 lines = []
556 for s in getsections(blocks):
643 for s in getsections(blocks):
557 section = s[0]
644 section = s[0]
558 text = formatblocks(s[2], width)
645 text = formatblocks(s[2], width)
559 lines.append([(section, l) for l in text.splitlines(True)])
646 lines.append([(section, l) for l in text.splitlines(True)])
560 return lines
647 return lines
561
648
562 def maketable(data, indent=0, header=False):
649 def maketable(data, indent=0, header=False):
563 '''Generate an RST table for the given table data'''
650 '''Generate an RST table for the given table data'''
564
651
565 widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
652 widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
566 indent = ' ' * indent
653 indent = ' ' * indent
567 div = indent + ' '.join('=' * w for w in widths) + '\n'
654 div = indent + ' '.join('=' * w for w in widths) + '\n'
568
655
569 out = [div]
656 out = [div]
570 for row in data:
657 for row in data:
571 l = []
658 l = []
572 for w, v in zip(widths, row):
659 for w, v in zip(widths, row):
573 pad = ' ' * (w - encoding.colwidth(v))
660 pad = ' ' * (w - encoding.colwidth(v))
574 l.append(v + pad)
661 l.append(v + pad)
575 out.append(indent + ' '.join(l) + "\n")
662 out.append(indent + ' '.join(l) + "\n")
576 if header and len(data) > 1:
663 if header and len(data) > 1:
577 out.insert(2, div)
664 out.insert(2, div)
578 out.append(div)
665 out.append(div)
579 return ''.join(out)
666 return ''.join(out)
@@ -1,244 +1,247 b''
1 from pprint import pprint
1 from pprint import pprint
2 from mercurial import minirst
2 from mercurial import minirst
3
3
4 def debugformat(title, text, width, **kwargs):
4 def debugformat(title, text, width, **kwargs):
5 print "%s formatted to fit within %d characters:" % (title, width)
5 print "%s formatted to fit within %d characters:" % (title, width)
6 formatted = minirst.format(text, width, **kwargs)
7 html = minirst.formathtml(minirst.parse(text, **kwargs)[0])
6 print "-" * 70
8 print "-" * 70
7 formatted = minirst.format(text, width, **kwargs)
8 if type(formatted) == tuple:
9 if type(formatted) == tuple:
9 print formatted[0]
10 print formatted[0]
10 print "-" * 70
11 print "-" * 70
11 pprint(formatted[1])
12 pprint(formatted[1])
12 else:
13 else:
13 print formatted
14 print formatted
14 print "-" * 70
15 print "-" * 70
16 print html
17 print "-" * 70
15 print
18 print
16
19
17 paragraphs = """
20 paragraphs = """
18 This is some text in the first paragraph.
21 This is some text in the first paragraph.
19
22
20 A small indented paragraph.
23 A small indented paragraph.
21 It is followed by some lines
24 It is followed by some lines
22 containing random whitespace.
25 containing random whitespace.
23 \n \n \nThe third and final paragraph.
26 \n \n \nThe third and final paragraph.
24 """
27 """
25
28
26 debugformat('paragraphs', paragraphs, 60)
29 debugformat('paragraphs', paragraphs, 60)
27 debugformat('paragraphs', paragraphs, 30)
30 debugformat('paragraphs', paragraphs, 30)
28
31
29
32
30 definitions = """
33 definitions = """
31 A Term
34 A Term
32 Definition. The indented
35 Definition. The indented
33 lines make up the definition.
36 lines make up the definition.
34 Another Term
37 Another Term
35 Another definition. The final line in the
38 Another definition. The final line in the
36 definition determines the indentation, so
39 definition determines the indentation, so
37 this will be indented with four spaces.
40 this will be indented with four spaces.
38
41
39 A Nested/Indented Term
42 A Nested/Indented Term
40 Definition.
43 Definition.
41 """
44 """
42
45
43 debugformat('definitions', definitions, 60)
46 debugformat('definitions', definitions, 60)
44 debugformat('definitions', definitions, 30)
47 debugformat('definitions', definitions, 30)
45
48
46
49
47 literals = r"""
50 literals = r"""
48 The fully minimized form is the most
51 The fully minimized form is the most
49 convenient form::
52 convenient form::
50
53
51 Hello
54 Hello
52 literal
55 literal
53 world
56 world
54
57
55 In the partially minimized form a paragraph
58 In the partially minimized form a paragraph
56 simply ends with space-double-colon. ::
59 simply ends with space-double-colon. ::
57
60
58 ////////////////////////////////////////
61 ////////////////////////////////////////
59 long un-wrapped line in a literal block
62 long un-wrapped line in a literal block
60 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
63 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
61
64
62 ::
65 ::
63
66
64 This literal block is started with '::',
67 This literal block is started with '::',
65 the so-called expanded form. The paragraph
68 the so-called expanded form. The paragraph
66 with '::' disappears in the final output.
69 with '::' disappears in the final output.
67 """
70 """
68
71
69 debugformat('literals', literals, 60)
72 debugformat('literals', literals, 60)
70 debugformat('literals', literals, 30)
73 debugformat('literals', literals, 30)
71
74
72
75
73 lists = """
76 lists = """
74 - This is the first list item.
77 - This is the first list item.
75
78
76 Second paragraph in the first list item.
79 Second paragraph in the first list item.
77
80
78 - List items need not be separated
81 - List items need not be separated
79 by a blank line.
82 by a blank line.
80 - And will be rendered without
83 - And will be rendered without
81 one in any case.
84 one in any case.
82
85
83 We can have indented lists:
86 We can have indented lists:
84
87
85 - This is an indented list item
88 - This is an indented list item
86
89
87 - Another indented list item::
90 - Another indented list item::
88
91
89 - A literal block in the middle
92 - A literal block in the middle
90 of an indented list.
93 of an indented list.
91
94
92 (The above is not a list item since we are in the literal block.)
95 (The above is not a list item since we are in the literal block.)
93
96
94 ::
97 ::
95
98
96 Literal block with no indentation (apart from
99 Literal block with no indentation (apart from
97 the two spaces added to all literal blocks).
100 the two spaces added to all literal blocks).
98
101
99 1. This is an enumerated list (first item).
102 1. This is an enumerated list (first item).
100 2. Continuing with the second item.
103 2. Continuing with the second item.
101
104
102 (1) foo
105 (1) foo
103 (2) bar
106 (2) bar
104
107
105 1) Another
108 1) Another
106 2) List
109 2) List
107
110
108 Line blocks are also a form of list:
111 Line blocks are also a form of list:
109
112
110 | This is the first line.
113 | This is the first line.
111 The line continues here.
114 The line continues here.
112 | This is the second line.
115 | This is the second line.
113 """
116 """
114
117
115 debugformat('lists', lists, 60)
118 debugformat('lists', lists, 60)
116 debugformat('lists', lists, 30)
119 debugformat('lists', lists, 30)
117
120
118
121
119 options = """
122 options = """
120 There is support for simple option lists,
123 There is support for simple option lists,
121 but only with long options:
124 but only with long options:
122
125
123 -X, --exclude filter an option with a short and long option with an argument
126 -X, --exclude filter an option with a short and long option with an argument
124 -I, --include an option with both a short option and a long option
127 -I, --include an option with both a short option and a long option
125 --all Output all.
128 --all Output all.
126 --both Output both (this description is
129 --both Output both (this description is
127 quite long).
130 quite long).
128 --long Output all day long.
131 --long Output all day long.
129
132
130 --par This option has two paragraphs in its description.
133 --par This option has two paragraphs in its description.
131 This is the first.
134 This is the first.
132
135
133 This is the second. Blank lines may be omitted between
136 This is the second. Blank lines may be omitted between
134 options (as above) or left in (as here).
137 options (as above) or left in (as here).
135
138
136
139
137 The next paragraph looks like an option list, but lacks the two-space
140 The next paragraph looks like an option list, but lacks the two-space
138 marker after the option. It is treated as a normal paragraph:
141 marker after the option. It is treated as a normal paragraph:
139
142
140 --foo bar baz
143 --foo bar baz
141 """
144 """
142
145
143 debugformat('options', options, 60)
146 debugformat('options', options, 60)
144 debugformat('options', options, 30)
147 debugformat('options', options, 30)
145
148
146
149
147 fields = """
150 fields = """
148 :a: First item.
151 :a: First item.
149 :ab: Second item. Indentation and wrapping
152 :ab: Second item. Indentation and wrapping
150 is handled automatically.
153 is handled automatically.
151
154
152 Next list:
155 Next list:
153
156
154 :small: The larger key below triggers full indentation here.
157 :small: The larger key below triggers full indentation here.
155 :much too large: This key is big enough to get its own line.
158 :much too large: This key is big enough to get its own line.
156 """
159 """
157
160
158 debugformat('fields', fields, 60)
161 debugformat('fields', fields, 60)
159 debugformat('fields', fields, 30)
162 debugformat('fields', fields, 30)
160
163
161 containers = """
164 containers = """
162 Normal output.
165 Normal output.
163
166
164 .. container:: debug
167 .. container:: debug
165
168
166 Initial debug output.
169 Initial debug output.
167
170
168 .. container:: verbose
171 .. container:: verbose
169
172
170 Verbose output.
173 Verbose output.
171
174
172 .. container:: debug
175 .. container:: debug
173
176
174 Debug output.
177 Debug output.
175 """
178 """
176
179
177 debugformat('containers (normal)', containers, 60)
180 debugformat('containers (normal)', containers, 60)
178 debugformat('containers (verbose)', containers, 60, keep=['verbose'])
181 debugformat('containers (verbose)', containers, 60, keep=['verbose'])
179 debugformat('containers (debug)', containers, 60, keep=['debug'])
182 debugformat('containers (debug)', containers, 60, keep=['debug'])
180 debugformat('containers (verbose debug)', containers, 60,
183 debugformat('containers (verbose debug)', containers, 60,
181 keep=['verbose', 'debug'])
184 keep=['verbose', 'debug'])
182
185
183 roles = """Please see :hg:`add`."""
186 roles = """Please see :hg:`add`."""
184 debugformat('roles', roles, 60)
187 debugformat('roles', roles, 60)
185
188
186
189
187 sections = """
190 sections = """
188 Title
191 Title
189 =====
192 =====
190
193
191 Section
194 Section
192 -------
195 -------
193
196
194 Subsection
197 Subsection
195 ''''''''''
198 ''''''''''
196
199
197 Markup: ``foo`` and :hg:`help`
200 Markup: ``foo`` and :hg:`help`
198 ------------------------------
201 ------------------------------
199 """
202 """
200 debugformat('sections', sections, 20)
203 debugformat('sections', sections, 20)
201
204
202
205
203 admonitions = """
206 admonitions = """
204 .. note::
207 .. note::
205 This is a note
208 This is a note
206
209
207 - Bullet 1
210 - Bullet 1
208 - Bullet 2
211 - Bullet 2
209
212
210 .. warning:: This is a warning Second
213 .. warning:: This is a warning Second
211 input line of warning
214 input line of warning
212
215
213 .. danger::
216 .. danger::
214 This is danger
217 This is danger
215 """
218 """
216
219
217 debugformat('admonitions', admonitions, 30)
220 debugformat('admonitions', admonitions, 30)
218
221
219 comments = """
222 comments = """
220 Some text.
223 Some text.
221
224
222 .. A comment
225 .. A comment
223
226
224 .. An indented comment
227 .. An indented comment
225
228
226 Some indented text.
229 Some indented text.
227
230
228 ..
231 ..
229
232
230 Empty comment above
233 Empty comment above
231 """
234 """
232
235
233 debugformat('comments', comments, 30)
236 debugformat('comments', comments, 30)
234
237
235
238
236 data = [['a', 'b', 'c'],
239 data = [['a', 'b', 'c'],
237 ['1', '2', '3'],
240 ['1', '2', '3'],
238 ['foo', 'bar', 'baz this list is very very very long man']]
241 ['foo', 'bar', 'baz this list is very very very long man']]
239
242
240 table = minirst.maketable(data, 2, True)
243 table = minirst.maketable(data, 2, True)
241
244
242 print table
245 print table
243
246
244 debugformat('table', table, 30)
247 debugformat('table', table, 30)
@@ -1,428 +1,785 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 <p>
12 This is some text in the first paragraph.
13 </p>
14 <p>
15 A small indented paragraph.
16 It is followed by some lines
17 containing random whitespace.
18 </p>
19 <p>
20 The third and final paragraph.
21 </p>
22
23 ----------------------------------------------------------------------
11
24
12 paragraphs formatted to fit within 30 characters:
25 paragraphs formatted to fit within 30 characters:
13 ----------------------------------------------------------------------
26 ----------------------------------------------------------------------
14 This is some text in the first
27 This is some text in the first
15 paragraph.
28 paragraph.
16
29
17 A small indented paragraph.
30 A small indented paragraph.
18 It is followed by some lines
31 It is followed by some lines
19 containing random
32 containing random
20 whitespace.
33 whitespace.
21
34
22 The third and final paragraph.
35 The third and final paragraph.
23
36
24 ----------------------------------------------------------------------
37 ----------------------------------------------------------------------
38 <p>
39 This is some text in the first paragraph.
40 </p>
41 <p>
42 A small indented paragraph.
43 It is followed by some lines
44 containing random whitespace.
45 </p>
46 <p>
47 The third and final paragraph.
48 </p>
49
50 ----------------------------------------------------------------------
25
51
26 definitions formatted to fit within 60 characters:
52 definitions formatted to fit within 60 characters:
27 ----------------------------------------------------------------------
53 ----------------------------------------------------------------------
28 A Term
54 A Term
29 Definition. The indented lines make up the definition.
55 Definition. The indented lines make up the definition.
30
56
31 Another Term
57 Another Term
32 Another definition. The final line in the definition
58 Another definition. The final line in the definition
33 determines the indentation, so this will be indented
59 determines the indentation, so this will be indented
34 with four spaces.
60 with four spaces.
35
61
36 A Nested/Indented Term
62 A Nested/Indented Term
37 Definition.
63 Definition.
38
64
39 ----------------------------------------------------------------------
65 ----------------------------------------------------------------------
66 <dl>
67 <dt>A Term
68 <dd>Definition. The indented lines make up the definition.
69 <dt>Another Term
70 <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
71 <dt>A Nested/Indented Term
72 <dd>Definition.
73 </dl>
74
75 ----------------------------------------------------------------------
40
76
41 definitions formatted to fit within 30 characters:
77 definitions formatted to fit within 30 characters:
42 ----------------------------------------------------------------------
78 ----------------------------------------------------------------------
43 A Term
79 A Term
44 Definition. The indented
80 Definition. The indented
45 lines make up the
81 lines make up the
46 definition.
82 definition.
47
83
48 Another Term
84 Another Term
49 Another definition. The
85 Another definition. The
50 final line in the
86 final line in the
51 definition determines the
87 definition determines the
52 indentation, so this will
88 indentation, so this will
53 be indented with four
89 be indented with four
54 spaces.
90 spaces.
55
91
56 A Nested/Indented Term
92 A Nested/Indented Term
57 Definition.
93 Definition.
58
94
59 ----------------------------------------------------------------------
95 ----------------------------------------------------------------------
96 <dl>
97 <dt>A Term
98 <dd>Definition. The indented lines make up the definition.
99 <dt>Another Term
100 <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
101 <dt>A Nested/Indented Term
102 <dd>Definition.
103 </dl>
104
105 ----------------------------------------------------------------------
60
106
61 literals formatted to fit within 60 characters:
107 literals formatted to fit within 60 characters:
62 ----------------------------------------------------------------------
108 ----------------------------------------------------------------------
63 The fully minimized form is the most convenient form:
109 The fully minimized form is the most convenient form:
64
110
65 Hello
111 Hello
66 literal
112 literal
67 world
113 world
68
114
69 In the partially minimized form a paragraph simply ends with
115 In the partially minimized form a paragraph simply ends with
70 space-double-colon.
116 space-double-colon.
71
117
72 ////////////////////////////////////////
118 ////////////////////////////////////////
73 long un-wrapped line in a literal block
119 long un-wrapped line in a literal block
74 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
120 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
75
121
76 This literal block is started with '::',
122 This literal block is started with '::',
77 the so-called expanded form. The paragraph
123 the so-called expanded form. The paragraph
78 with '::' disappears in the final output.
124 with '::' disappears in the final output.
79
125
80 ----------------------------------------------------------------------
126 ----------------------------------------------------------------------
127 <p>
128 The fully minimized form is the most
129 convenient form:
130 </p>
131 <pre>
132 Hello
133 literal
134 world
135 </pre>
136 <p>
137 In the partially minimized form a paragraph
138 simply ends with space-double-colon.
139 </p>
140 <pre>
141 ////////////////////////////////////////
142 long un-wrapped line in a literal block
143 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
144 </pre>
145 <pre>
146 This literal block is started with '::',
147 the so-called expanded form. The paragraph
148 with '::' disappears in the final output.
149 </pre>
150
151 ----------------------------------------------------------------------
81
152
82 literals formatted to fit within 30 characters:
153 literals formatted to fit within 30 characters:
83 ----------------------------------------------------------------------
154 ----------------------------------------------------------------------
84 The fully minimized form is
155 The fully minimized form is
85 the most convenient form:
156 the most convenient form:
86
157
87 Hello
158 Hello
88 literal
159 literal
89 world
160 world
90
161
91 In the partially minimized
162 In the partially minimized
92 form a paragraph simply ends
163 form a paragraph simply ends
93 with space-double-colon.
164 with space-double-colon.
94
165
95 ////////////////////////////////////////
166 ////////////////////////////////////////
96 long un-wrapped line in a literal block
167 long un-wrapped line in a literal block
97 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
168 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
98
169
99 This literal block is started with '::',
170 This literal block is started with '::',
100 the so-called expanded form. The paragraph
171 the so-called expanded form. The paragraph
101 with '::' disappears in the final output.
172 with '::' disappears in the final output.
102
173
103 ----------------------------------------------------------------------
174 ----------------------------------------------------------------------
175 <p>
176 The fully minimized form is the most
177 convenient form:
178 </p>
179 <pre>
180 Hello
181 literal
182 world
183 </pre>
184 <p>
185 In the partially minimized form a paragraph
186 simply ends with space-double-colon.
187 </p>
188 <pre>
189 ////////////////////////////////////////
190 long un-wrapped line in a literal block
191 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
192 </pre>
193 <pre>
194 This literal block is started with '::',
195 the so-called expanded form. The paragraph
196 with '::' disappears in the final output.
197 </pre>
198
199 ----------------------------------------------------------------------
104
200
105 lists formatted to fit within 60 characters:
201 lists formatted to fit within 60 characters:
106 ----------------------------------------------------------------------
202 ----------------------------------------------------------------------
107 - This is the first list item.
203 - This is the first list item.
108
204
109 Second paragraph in the first list item.
205 Second paragraph in the first list item.
110
206
111 - List items need not be separated by a blank line.
207 - List items need not be separated by a blank line.
112 - And will be rendered without one in any case.
208 - And will be rendered without one in any case.
113
209
114 We can have indented lists:
210 We can have indented lists:
115
211
116 - This is an indented list item
212 - This is an indented list item
117 - Another indented list item:
213 - Another indented list item:
118
214
119 - A literal block in the middle
215 - A literal block in the middle
120 of an indented list.
216 of an indented list.
121
217
122 (The above is not a list item since we are in the literal block.)
218 (The above is not a list item since we are in the literal block.)
123
219
124 Literal block with no indentation (apart from
220 Literal block with no indentation (apart from
125 the two spaces added to all literal blocks).
221 the two spaces added to all literal blocks).
126
222
127 1. This is an enumerated list (first item).
223 1. This is an enumerated list (first item).
128 2. Continuing with the second item.
224 2. Continuing with the second item.
129 (1) foo
225 (1) foo
130 (2) bar
226 (2) bar
131 1) Another
227 1) Another
132 2) List
228 2) List
133
229
134 Line blocks are also a form of list:
230 Line blocks are also a form of list:
135
231
136 This is the first line. The line continues here.
232 This is the first line. The line continues here.
137 This is the second line.
233 This is the second line.
138
234
139 ----------------------------------------------------------------------
235 ----------------------------------------------------------------------
236 <ul>
237 <li> This is the first list item.
238 <p>
239 Second paragraph in the first list item.
240 </p>
241 <li> List items need not be separated by a blank line.
242 <li> And will be rendered without one in any case.
243 </ul>
244 <p>
245 We can have indented lists:
246 </p>
247 <ul>
248 <li> This is an indented list item
249 <li> Another indented list item:
250 <pre>
251 - A literal block in the middle
252 of an indented list.
253 </pre>
254 <pre>
255 (The above is not a list item since we are in the literal block.)
256 </pre>
257 </ul>
258 <pre>
259 Literal block with no indentation (apart from
260 the two spaces added to all literal blocks).
261 </pre>
262 <ol>
263 <li> This is an enumerated list (first item).
264 <li> Continuing with the second item.
265 <li> foo
266 <li> bar
267 <li> Another
268 <li> List
269 </ol>
270 <p>
271 Line blocks are also a form of list:
272 </p>
273 <ol>
274 <li> This is the first line. The line continues here.
275 <li> This is the second line.
276 </ol>
277
278 ----------------------------------------------------------------------
140
279
141 lists formatted to fit within 30 characters:
280 lists formatted to fit within 30 characters:
142 ----------------------------------------------------------------------
281 ----------------------------------------------------------------------
143 - This is the first list item.
282 - This is the first list item.
144
283
145 Second paragraph in the
284 Second paragraph in the
146 first list item.
285 first list item.
147
286
148 - List items need not be
287 - List items need not be
149 separated by a blank line.
288 separated by a blank line.
150 - And will be rendered without
289 - And will be rendered without
151 one in any case.
290 one in any case.
152
291
153 We can have indented lists:
292 We can have indented lists:
154
293
155 - This is an indented list
294 - This is an indented list
156 item
295 item
157 - Another indented list
296 - Another indented list
158 item:
297 item:
159
298
160 - A literal block in the middle
299 - A literal block in the middle
161 of an indented list.
300 of an indented list.
162
301
163 (The above is not a list item since we are in the literal block.)
302 (The above is not a list item since we are in the literal block.)
164
303
165 Literal block with no indentation (apart from
304 Literal block with no indentation (apart from
166 the two spaces added to all literal blocks).
305 the two spaces added to all literal blocks).
167
306
168 1. This is an enumerated list
307 1. This is an enumerated list
169 (first item).
308 (first item).
170 2. Continuing with the second
309 2. Continuing with the second
171 item.
310 item.
172 (1) foo
311 (1) foo
173 (2) bar
312 (2) bar
174 1) Another
313 1) Another
175 2) List
314 2) List
176
315
177 Line blocks are also a form of
316 Line blocks are also a form of
178 list:
317 list:
179
318
180 This is the first line. The
319 This is the first line. The
181 line continues here.
320 line continues here.
182 This is the second line.
321 This is the second line.
183
322
184 ----------------------------------------------------------------------
323 ----------------------------------------------------------------------
324 <ul>
325 <li> This is the first list item.
326 <p>
327 Second paragraph in the first list item.
328 </p>
329 <li> List items need not be separated by a blank line.
330 <li> And will be rendered without one in any case.
331 </ul>
332 <p>
333 We can have indented lists:
334 </p>
335 <ul>
336 <li> This is an indented list item
337 <li> Another indented list item:
338 <pre>
339 - A literal block in the middle
340 of an indented list.
341 </pre>
342 <pre>
343 (The above is not a list item since we are in the literal block.)
344 </pre>
345 </ul>
346 <pre>
347 Literal block with no indentation (apart from
348 the two spaces added to all literal blocks).
349 </pre>
350 <ol>
351 <li> This is an enumerated list (first item).
352 <li> Continuing with the second item.
353 <li> foo
354 <li> bar
355 <li> Another
356 <li> List
357 </ol>
358 <p>
359 Line blocks are also a form of list:
360 </p>
361 <ol>
362 <li> This is the first line. The line continues here.
363 <li> This is the second line.
364 </ol>
365
366 ----------------------------------------------------------------------
185
367
186 options formatted to fit within 60 characters:
368 options formatted to fit within 60 characters:
187 ----------------------------------------------------------------------
369 ----------------------------------------------------------------------
188 There is support for simple option lists, but only with long
370 There is support for simple option lists, but only with long
189 options:
371 options:
190
372
191 -X --exclude filter an option with a short and long option
373 -X --exclude filter an option with a short and long option
192 with an argument
374 with an argument
193 -I --include an option with both a short option and
375 -I --include an option with both a short option and
194 a long option
376 a long option
195 --all Output all.
377 --all Output all.
196 --both Output both (this description is quite
378 --both Output both (this description is quite
197 long).
379 long).
198 --long Output all day long.
380 --long Output all day long.
199 --par This option has two paragraphs in its
381 --par This option has two paragraphs in its
200 description. This is the first.
382 description. This is the first.
201
383
202 This is the second. Blank lines may
384 This is the second. Blank lines may
203 be omitted between options (as above)
385 be omitted between options (as above)
204 or left in (as here).
386 or left in (as here).
205
387
206 The next paragraph looks like an option list, but lacks the
388 The next paragraph looks like an option list, but lacks the
207 two-space marker after the option. It is treated as a normal
389 two-space marker after the option. It is treated as a normal
208 paragraph:
390 paragraph:
209
391
210 --foo bar baz
392 --foo bar baz
211
393
212 ----------------------------------------------------------------------
394 ----------------------------------------------------------------------
395 <p>
396 There is support for simple option lists,
397 but only with long options:
398 </p>
399 <dl>
400 <dt>-X --exclude filter
401 <dd>an option with a short and long option with an argument
402 <dt>-I --include
403 <dd>an option with both a short option and a long option
404 <dt> --all
405 <dd>Output all.
406 <dt> --both
407 <dd>Output both (this description is quite long).
408 <dt> --long
409 <dd>Output all day long.
410 <dt> --par
411 <dd>This option has two paragraphs in its description. This is the first.
412 <p>
413 This is the second. Blank lines may be omitted between
414 options (as above) or left in (as here).
415 </p>
416 </dl>
417 <p>
418 The next paragraph looks like an option list, but lacks the two-space
419 marker after the option. It is treated as a normal paragraph:
420 </p>
421 <p>
422 --foo bar baz
423 </p>
424
425 ----------------------------------------------------------------------
213
426
214 options formatted to fit within 30 characters:
427 options formatted to fit within 30 characters:
215 ----------------------------------------------------------------------
428 ----------------------------------------------------------------------
216 There is support for simple
429 There is support for simple
217 option lists, but only with
430 option lists, but only with
218 long options:
431 long options:
219
432
220 -X --exclude filter an
433 -X --exclude filter an
221 option
434 option
222 with a
435 with a
223 short
436 short
224 and
437 and
225 long
438 long
226 option
439 option
227 with an
440 with an
228 argumen
441 argumen
229 t
442 t
230 -I --include an
443 -I --include an
231 option
444 option
232 with
445 with
233 both a
446 both a
234 short
447 short
235 option
448 option
236 and a
449 and a
237 long
450 long
238 option
451 option
239 --all Output
452 --all Output
240 all.
453 all.
241 --both Output
454 --both Output
242 both
455 both
243 (this d
456 (this d
244 escript
457 escript
245 ion is
458 ion is
246 quite
459 quite
247 long).
460 long).
248 --long Output
461 --long Output
249 all day
462 all day
250 long.
463 long.
251 --par This
464 --par This
252 option
465 option
253 has two
466 has two
254 paragra
467 paragra
255 phs in
468 phs in
256 its des
469 its des
257 criptio
470 criptio
258 n. This
471 n. This
259 is the
472 is the
260 first.
473 first.
261
474
262 This is
475 This is
263 the
476 the
264 second.
477 second.
265 Blank
478 Blank
266 lines
479 lines
267 may be
480 may be
268 omitted
481 omitted
269 between
482 between
270 options
483 options
271 (as
484 (as
272 above)
485 above)
273 or left
486 or left
274 in (as
487 in (as
275 here).
488 here).
276
489
277 The next paragraph looks like
490 The next paragraph looks like
278 an option list, but lacks the
491 an option list, but lacks the
279 two-space marker after the
492 two-space marker after the
280 option. It is treated as a
493 option. It is treated as a
281 normal paragraph:
494 normal paragraph:
282
495
283 --foo bar baz
496 --foo bar baz
284
497
285 ----------------------------------------------------------------------
498 ----------------------------------------------------------------------
499 <p>
500 There is support for simple option lists,
501 but only with long options:
502 </p>
503 <dl>
504 <dt>-X --exclude filter
505 <dd>an option with a short and long option with an argument
506 <dt>-I --include
507 <dd>an option with both a short option and a long option
508 <dt> --all
509 <dd>Output all.
510 <dt> --both
511 <dd>Output both (this description is quite long).
512 <dt> --long
513 <dd>Output all day long.
514 <dt> --par
515 <dd>This option has two paragraphs in its description. This is the first.
516 <p>
517 This is the second. Blank lines may be omitted between
518 options (as above) or left in (as here).
519 </p>
520 </dl>
521 <p>
522 The next paragraph looks like an option list, but lacks the two-space
523 marker after the option. It is treated as a normal paragraph:
524 </p>
525 <p>
526 --foo bar baz
527 </p>
528
529 ----------------------------------------------------------------------
286
530
287 fields formatted to fit within 60 characters:
531 fields formatted to fit within 60 characters:
288 ----------------------------------------------------------------------
532 ----------------------------------------------------------------------
289 a First item.
533 a First item.
290 ab Second item. Indentation and wrapping is handled
534 ab Second item. Indentation and wrapping is handled
291 automatically.
535 automatically.
292
536
293 Next list:
537 Next list:
294
538
295 small The larger key below triggers full indentation
539 small The larger key below triggers full indentation
296 here.
540 here.
297 much too large
541 much too large
298 This key is big enough to get its own line.
542 This key is big enough to get its own line.
299
543
300 ----------------------------------------------------------------------
544 ----------------------------------------------------------------------
545 <dl>
546 <dt>a
547 <dd>First item.
548 <dt>ab
549 <dd>Second item. Indentation and wrapping is handled automatically.
550 </dl>
551 <p>
552 Next list:
553 </p>
554 <dl>
555 <dt>small
556 <dd>The larger key below triggers full indentation here.
557 <dt>much too large
558 <dd>This key is big enough to get its own line.
559 </dl>
560
561 ----------------------------------------------------------------------
301
562
302 fields formatted to fit within 30 characters:
563 fields formatted to fit within 30 characters:
303 ----------------------------------------------------------------------
564 ----------------------------------------------------------------------
304 a First item.
565 a First item.
305 ab Second item. Indentation
566 ab Second item. Indentation
306 and wrapping is handled
567 and wrapping is handled
307 automatically.
568 automatically.
308
569
309 Next list:
570 Next list:
310
571
311 small The larger key
572 small The larger key
312 below triggers
573 below triggers
313 full indentation
574 full indentation
314 here.
575 here.
315 much too large
576 much too large
316 This key is big
577 This key is big
317 enough to get its
578 enough to get its
318 own line.
579 own line.
319
580
320 ----------------------------------------------------------------------
581 ----------------------------------------------------------------------
582 <dl>
583 <dt>a
584 <dd>First item.
585 <dt>ab
586 <dd>Second item. Indentation and wrapping is handled automatically.
587 </dl>
588 <p>
589 Next list:
590 </p>
591 <dl>
592 <dt>small
593 <dd>The larger key below triggers full indentation here.
594 <dt>much too large
595 <dd>This key is big enough to get its own line.
596 </dl>
597
598 ----------------------------------------------------------------------
321
599
322 containers (normal) formatted to fit within 60 characters:
600 containers (normal) formatted to fit within 60 characters:
323 ----------------------------------------------------------------------
601 ----------------------------------------------------------------------
324 Normal output.
602 Normal output.
325
603
326 ----------------------------------------------------------------------
604 ----------------------------------------------------------------------
605 <p>
606 Normal output.
607 </p>
608
609 ----------------------------------------------------------------------
327
610
328 containers (verbose) formatted to fit within 60 characters:
611 containers (verbose) formatted to fit within 60 characters:
329 ----------------------------------------------------------------------
612 ----------------------------------------------------------------------
330 Normal output.
613 Normal output.
331
614
332 Verbose output.
615 Verbose output.
333
616
334 ----------------------------------------------------------------------
617 ----------------------------------------------------------------------
335 ['debug', 'debug']
618 ['debug', 'debug']
336 ----------------------------------------------------------------------
619 ----------------------------------------------------------------------
620 <p>
621 Normal output.
622 </p>
623 <p>
624 Verbose output.
625 </p>
626
627 ----------------------------------------------------------------------
337
628
338 containers (debug) formatted to fit within 60 characters:
629 containers (debug) formatted to fit within 60 characters:
339 ----------------------------------------------------------------------
630 ----------------------------------------------------------------------
340 Normal output.
631 Normal output.
341
632
342 Initial debug output.
633 Initial debug output.
343
634
344 ----------------------------------------------------------------------
635 ----------------------------------------------------------------------
345 ['verbose']
636 ['verbose']
346 ----------------------------------------------------------------------
637 ----------------------------------------------------------------------
638 <p>
639 Normal output.
640 </p>
641 <p>
642 Initial debug output.
643 </p>
644
645 ----------------------------------------------------------------------
347
646
348 containers (verbose debug) formatted to fit within 60 characters:
647 containers (verbose debug) formatted to fit within 60 characters:
349 ----------------------------------------------------------------------
648 ----------------------------------------------------------------------
350 Normal output.
649 Normal output.
351
650
352 Initial debug output.
651 Initial debug output.
353
652
354 Verbose output.
653 Verbose output.
355
654
356 Debug output.
655 Debug output.
357
656
358 ----------------------------------------------------------------------
657 ----------------------------------------------------------------------
359 []
658 []
360 ----------------------------------------------------------------------
659 ----------------------------------------------------------------------
660 <p>
661 Normal output.
662 </p>
663 <p>
664 Initial debug output.
665 </p>
666 <p>
667 Verbose output.
668 </p>
669 <p>
670 Debug output.
671 </p>
672
673 ----------------------------------------------------------------------
361
674
362 roles formatted to fit within 60 characters:
675 roles formatted to fit within 60 characters:
363 ----------------------------------------------------------------------
676 ----------------------------------------------------------------------
364 Please see "hg add".
677 Please see "hg add".
365
678
366 ----------------------------------------------------------------------
679 ----------------------------------------------------------------------
680 <p>
681 Please see "hg add".
682 </p>
683
684 ----------------------------------------------------------------------
367
685
368 sections formatted to fit within 20 characters:
686 sections formatted to fit within 20 characters:
369 ----------------------------------------------------------------------
687 ----------------------------------------------------------------------
370 Title
688 Title
371 =====
689 =====
372
690
373 Section
691 Section
374 -------
692 -------
375
693
376 Subsection
694 Subsection
377 ''''''''''
695 ''''''''''
378
696
379 Markup: "foo" and "hg help"
697 Markup: "foo" and "hg help"
380 ---------------------------
698 ---------------------------
381
699
382 ----------------------------------------------------------------------
700 ----------------------------------------------------------------------
701 <h1>Title</h1>
702 <h2>Section</h2>
703 <h3>Subsection</h3>
704 <h2>Markup: "foo" and "hg help"</h2>
705
706 ----------------------------------------------------------------------
383
707
384 admonitions formatted to fit within 30 characters:
708 admonitions formatted to fit within 30 characters:
385 ----------------------------------------------------------------------
709 ----------------------------------------------------------------------
386 Note:
710 Note:
387 This is a note
711 This is a note
388
712
389 - Bullet 1
713 - Bullet 1
390 - Bullet 2
714 - Bullet 2
391
715
392 Warning!
716 Warning!
393 This is a warning Second
717 This is a warning Second
394 input line of warning
718 input line of warning
395
719
396 !Danger!
720 !Danger!
397 This is danger
721 This is danger
398
722
399 ----------------------------------------------------------------------
723 ----------------------------------------------------------------------
724 <p>
725 <b>Note:</b> This is a note
726 </p>
727 <ul>
728 <li> Bullet 1
729 <li> Bullet 2
730 </ul>
731 <p>
732 <b>Warning!</b> This is a warning Second input line of warning
733 </p>
734 <p>
735 <b>!Danger!</b> This is danger
736 </p>
737
738 ----------------------------------------------------------------------
400
739
401 comments formatted to fit within 30 characters:
740 comments formatted to fit within 30 characters:
402 ----------------------------------------------------------------------
741 ----------------------------------------------------------------------
403 Some text.
742 Some text.
404
743
405 Some indented text.
744 Some indented text.
406
745
407 Empty comment above
746 Empty comment above
408
747
409 ----------------------------------------------------------------------
748 ----------------------------------------------------------------------
749 <p>
750 Some text.
751 </p>
752 <p>
753 Some indented text.
754 </p>
755 <p>
756 Empty comment above
757 </p>
758
759 ----------------------------------------------------------------------
410
760
411 === === ========================================
761 === === ========================================
412 a b c
762 a b c
413 === === ========================================
763 === === ========================================
414 1 2 3
764 1 2 3
415 foo bar baz this list is very very very long man
765 foo bar baz this list is very very very long man
416 === === ========================================
766 === === ========================================
417
767
418 table formatted to fit within 30 characters:
768 table formatted to fit within 30 characters:
419 ----------------------------------------------------------------------
769 ----------------------------------------------------------------------
420 a b c
770 a b c
421 ------------------------------
771 ------------------------------
422 1 2 3
772 1 2 3
423 foo bar baz this list is
773 foo bar baz this list is
424 very very very long
774 very very very long
425 man
775 man
426
776
427 ----------------------------------------------------------------------
777 ----------------------------------------------------------------------
778 <table>
779 <tr><th>a</th><th>b</th><th>c</th></tr>
780 <tr><td>1</td><td>2</td><td>3</td></tr>
781 <tr><td>foo</td><td>bar</td><td>baz this list is very very very long man</td></tr>
782 </table>
428
783
784 ----------------------------------------------------------------------
785
General Comments 0
You need to be logged in to leave comments. Login now