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