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