Show More
@@ -0,0 +1,299 b'' | |||||
|
1 | # minirst.py - minimal reStructuredText parser | |||
|
2 | # | |||
|
3 | # Copyright 2009 Matt Mackall <mpm@selenic.com> and others | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2, incorporated herein by reference. | |||
|
7 | ||||
|
8 | """simplified reStructuredText parser. | |||
|
9 | ||||
|
10 | This parser knows just enough about reStructuredText to parse the | |||
|
11 | Mercurial docstrings. | |||
|
12 | ||||
|
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 | |||
|
15 | on the user to keep the right indentation for the blocks. | |||
|
16 | ||||
|
17 | It only supports a small subset of reStructuredText: | |||
|
18 | ||||
|
19 | - paragraphs | |||
|
20 | ||||
|
21 | - definition lists (must use ' ' to indent definitions) | |||
|
22 | ||||
|
23 | - lists (items must start with '-') | |||
|
24 | ||||
|
25 | - literal blocks | |||
|
26 | ||||
|
27 | - option lists (supports only long options without arguments) | |||
|
28 | ||||
|
29 | - inline markup is not recognized at all. | |||
|
30 | """ | |||
|
31 | ||||
|
32 | import re, sys, textwrap | |||
|
33 | ||||
|
34 | ||||
|
35 | def findblocks(text): | |||
|
36 | """Find continuous blocks of lines in text. | |||
|
37 | ||||
|
38 | Returns a list of dictionaries representing the blocks. Each block | |||
|
39 | has an 'indent' field and a 'lines' field. | |||
|
40 | """ | |||
|
41 | blocks = [[]] | |||
|
42 | lines = text.splitlines() | |||
|
43 | for line in lines: | |||
|
44 | if line.strip(): | |||
|
45 | blocks[-1].append(line) | |||
|
46 | elif blocks[-1]: | |||
|
47 | blocks.append([]) | |||
|
48 | if not blocks[-1]: | |||
|
49 | del blocks[-1] | |||
|
50 | ||||
|
51 | for i, block in enumerate(blocks): | |||
|
52 | indent = min((len(l) - len(l.lstrip())) for l in block) | |||
|
53 | blocks[i] = dict(indent=indent, lines=[l[indent:] for l in block]) | |||
|
54 | return blocks | |||
|
55 | ||||
|
56 | ||||
|
57 | def findliteralblocks(blocks): | |||
|
58 | """Finds literal blocks and adds a 'type' field to the blocks. | |||
|
59 | ||||
|
60 | Literal blocks are given the type 'literal', all other blocks are | |||
|
61 | given type the 'paragraph'. | |||
|
62 | """ | |||
|
63 | i = 0 | |||
|
64 | while i < len(blocks): | |||
|
65 | # Searching for a block that looks like this: | |||
|
66 | # | |||
|
67 | # +------------------------------+ | |||
|
68 | # | paragraph | | |||
|
69 | # | (ends with "::") | | |||
|
70 | # +------------------------------+ | |||
|
71 | # +---------------------------+ | |||
|
72 | # | indented literal block | | |||
|
73 | # +---------------------------+ | |||
|
74 | blocks[i]['type'] = 'paragraph' | |||
|
75 | if blocks[i]['lines'][-1].endswith('::') and i+1 < len(blocks): | |||
|
76 | indent = blocks[i]['indent'] | |||
|
77 | adjustment = blocks[i+1]['indent'] - indent | |||
|
78 | ||||
|
79 | if blocks[i]['lines'] == ['::']: | |||
|
80 | # Expanded form: remove block | |||
|
81 | del blocks[i] | |||
|
82 | i -= 1 | |||
|
83 | elif blocks[i]['lines'][-1].endswith(' ::'): | |||
|
84 | # Partially minimized form: remove space and both | |||
|
85 | # colons. | |||
|
86 | blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3] | |||
|
87 | else: | |||
|
88 | # Fully minimized form: remove just one colon. | |||
|
89 | blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1] | |||
|
90 | ||||
|
91 | # List items are formatted with a hanging indent. We must | |||
|
92 | # correct for this here while we still have the original | |||
|
93 | # information on the indentation of the subsequent literal | |||
|
94 | # blocks available. | |||
|
95 | if blocks[i]['lines'][0].startswith('- '): | |||
|
96 | indent += 2 | |||
|
97 | adjustment -= 2 | |||
|
98 | ||||
|
99 | # Mark the following indented blocks. | |||
|
100 | while i+1 < len(blocks) and blocks[i+1]['indent'] > indent: | |||
|
101 | blocks[i+1]['type'] = 'literal' | |||
|
102 | blocks[i+1]['indent'] -= adjustment | |||
|
103 | i += 1 | |||
|
104 | i += 1 | |||
|
105 | return blocks | |||
|
106 | ||||
|
107 | ||||
|
108 | def findsections(blocks): | |||
|
109 | """Finds sections. | |||
|
110 | ||||
|
111 | The blocks must have a 'type' field, i.e., they should have been | |||
|
112 | run through findliteralblocks first. | |||
|
113 | """ | |||
|
114 | for block in blocks: | |||
|
115 | # Searching for a block that looks like this: | |||
|
116 | # | |||
|
117 | # +------------------------------+ | |||
|
118 | # | Section title | | |||
|
119 | # | ------------- | | |||
|
120 | # +------------------------------+ | |||
|
121 | if (block['type'] == 'paragraph' and | |||
|
122 | len(block['lines']) == 2 and | |||
|
123 | block['lines'][1] == '-' * len(block['lines'][0])): | |||
|
124 | block['type'] = 'section' | |||
|
125 | return blocks | |||
|
126 | ||||
|
127 | ||||
|
128 | def findbulletlists(blocks): | |||
|
129 | """Finds bullet lists. | |||
|
130 | ||||
|
131 | The blocks must have a 'type' field, i.e., they should have been | |||
|
132 | run through findliteralblocks first. | |||
|
133 | """ | |||
|
134 | i = 0 | |||
|
135 | while i < len(blocks): | |||
|
136 | # Searching for a paragraph that looks like this: | |||
|
137 | # | |||
|
138 | # +------+-----------------------+ | |||
|
139 | # | "- " | list item | | |||
|
140 | # +------| (body elements)+ | | |||
|
141 | # +-----------------------+ | |||
|
142 | if (blocks[i]['type'] == 'paragraph' and | |||
|
143 | blocks[i]['lines'][0].startswith('- ')): | |||
|
144 | items = [] | |||
|
145 | for line in blocks[i]['lines']: | |||
|
146 | if line.startswith('- '): | |||
|
147 | items.append(dict(type='bullet', lines=[], | |||
|
148 | indent=blocks[i]['indent'] + 2)) | |||
|
149 | line = line[2:] | |||
|
150 | items[-1]['lines'].append(line) | |||
|
151 | blocks[i:i+1] = items | |||
|
152 | i += len(items) - 1 | |||
|
153 | i += 1 | |||
|
154 | return blocks | |||
|
155 | ||||
|
156 | ||||
|
157 | _optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$') | |||
|
158 | def findoptionlists(blocks): | |||
|
159 | """Finds option lists. | |||
|
160 | ||||
|
161 | The blocks must have a 'type' field, i.e., they should have been | |||
|
162 | run through findliteralblocks first. | |||
|
163 | """ | |||
|
164 | i = 0 | |||
|
165 | while i < len(blocks): | |||
|
166 | # Searching for a paragraph that looks like this: | |||
|
167 | # | |||
|
168 | # +----------------------------+-------------+ | |||
|
169 | # | "--" option " " | description | | |||
|
170 | # +-------+--------------------+ | | |||
|
171 | # | (body elements)+ | | |||
|
172 | # +----------------------------------+ | |||
|
173 | if (blocks[i]['type'] == 'paragraph' and | |||
|
174 | _optionre.match(blocks[i]['lines'][0])): | |||
|
175 | options = [] | |||
|
176 | for line in blocks[i]['lines']: | |||
|
177 | m = _optionre.match(line) | |||
|
178 | if m: | |||
|
179 | option, arg, rest = m.groups() | |||
|
180 | width = len(option) + len(arg) | |||
|
181 | options.append(dict(type='option', lines=[], | |||
|
182 | indent=blocks[i]['indent'], | |||
|
183 | width=width)) | |||
|
184 | options[-1]['lines'].append(line) | |||
|
185 | blocks[i:i+1] = options | |||
|
186 | i += len(options) - 1 | |||
|
187 | i += 1 | |||
|
188 | return blocks | |||
|
189 | ||||
|
190 | ||||
|
191 | def finddefinitionlists(blocks): | |||
|
192 | """Finds definition lists. | |||
|
193 | ||||
|
194 | The blocks must have a 'type' field, i.e., they should have been | |||
|
195 | run through findliteralblocks first. | |||
|
196 | """ | |||
|
197 | i = 0 | |||
|
198 | while i < len(blocks): | |||
|
199 | # Searching for a paragraph that looks like this: | |||
|
200 | # | |||
|
201 | # +----------------------------+ | |||
|
202 | # | term | | |||
|
203 | # +--+-------------------------+--+ | |||
|
204 | # | definition | | |||
|
205 | # | (body elements)+ | | |||
|
206 | # +----------------------------+ | |||
|
207 | if (blocks[i]['type'] == 'paragraph' and | |||
|
208 | len(blocks[i]['lines']) > 1 and | |||
|
209 | not blocks[i]['lines'][0].startswith(' ') and | |||
|
210 | blocks[i]['lines'][1].startswith(' ')): | |||
|
211 | definitions = [] | |||
|
212 | for line in blocks[i]['lines']: | |||
|
213 | if not line.startswith(' '): | |||
|
214 | definitions.append(dict(type='definition', lines=[], | |||
|
215 | indent=blocks[i]['indent'])) | |||
|
216 | definitions[-1]['lines'].append(line) | |||
|
217 | definitions[-1]['hang'] = len(line) - len(line.lstrip()) | |||
|
218 | blocks[i:i+1] = definitions | |||
|
219 | i += len(definitions) - 1 | |||
|
220 | i += 1 | |||
|
221 | return blocks | |||
|
222 | ||||
|
223 | ||||
|
224 | def addmargins(blocks): | |||
|
225 | """Adds empty blocks for vertical spacing. | |||
|
226 | ||||
|
227 | This groups bullets, options, and definitions together with no vertical | |||
|
228 | space between them, and adds an empty block between all other blocks. | |||
|
229 | """ | |||
|
230 | i = 1 | |||
|
231 | while i < len(blocks): | |||
|
232 | if (blocks[i]['type'] == blocks[i-1]['type'] and | |||
|
233 | blocks[i]['type'] in ('bullet', 'option', 'definition')): | |||
|
234 | i += 1 | |||
|
235 | else: | |||
|
236 | blocks.insert(i, dict(lines=[''], indent=0, type='margin')) | |||
|
237 | i += 2 | |||
|
238 | return blocks | |||
|
239 | ||||
|
240 | ||||
|
241 | def formatblock(block, width): | |||
|
242 | """Format a block according to width.""" | |||
|
243 | indent = ' ' * block['indent'] | |||
|
244 | if block['type'] == 'margin': | |||
|
245 | return '' | |||
|
246 | elif block['type'] in ('literal', 'section'): | |||
|
247 | return indent + ('\n' + indent).join(block['lines']) | |||
|
248 | elif block['type'] == 'definition': | |||
|
249 | term = indent + block['lines'][0] | |||
|
250 | defindent = indent + block['hang'] * ' ' | |||
|
251 | text = ' '.join(map(str.strip, block['lines'][1:])) | |||
|
252 | return "%s\n%s" % (term, textwrap.fill(text, width=width, | |||
|
253 | initial_indent=defindent, | |||
|
254 | subsequent_indent=defindent)) | |||
|
255 | else: | |||
|
256 | initindent = subindent = indent | |||
|
257 | text = ' '.join(map(str.strip, block['lines'])) | |||
|
258 | if block['type'] == 'bullet': | |||
|
259 | initindent = indent[:-2] + '- ' | |||
|
260 | subindent = indent | |||
|
261 | elif block['type'] == 'option': | |||
|
262 | subindent = indent + block['width'] * ' ' | |||
|
263 | ||||
|
264 | return textwrap.fill(text, width=width, | |||
|
265 | initial_indent=initindent, | |||
|
266 | subsequent_indent=subindent) | |||
|
267 | ||||
|
268 | ||||
|
269 | def format(text, width): | |||
|
270 | """Parse and format the text according to width.""" | |||
|
271 | blocks = findblocks(text) | |||
|
272 | blocks = findliteralblocks(blocks) | |||
|
273 | blocks = findsections(blocks) | |||
|
274 | blocks = findbulletlists(blocks) | |||
|
275 | blocks = findoptionlists(blocks) | |||
|
276 | blocks = finddefinitionlists(blocks) | |||
|
277 | blocks = addmargins(blocks) | |||
|
278 | return '\n'.join(formatblock(b, width) for b in blocks) | |||
|
279 | ||||
|
280 | ||||
|
281 | if __name__ == "__main__": | |||
|
282 | from pprint import pprint | |||
|
283 | ||||
|
284 | def debug(func, blocks): | |||
|
285 | blocks = func(blocks) | |||
|
286 | print "*** after %s:" % func.__name__ | |||
|
287 | pprint(blocks) | |||
|
288 | ||||
|
289 | return blocks | |||
|
290 | ||||
|
291 | text = open(sys.argv[1]).read() | |||
|
292 | blocks = debug(findblocks, text) | |||
|
293 | blocks = debug(findliteralblocks, blocks) | |||
|
294 | blocks = debug(findsections, blocks) | |||
|
295 | blocks = debug(findbulletlists, blocks) | |||
|
296 | blocks = debug(findoptionlists, blocks) | |||
|
297 | blocks = debug(finddefinitionlists, blocks) | |||
|
298 | blocks = debug(addmargins, blocks) | |||
|
299 | print '\n'.join(formatblock(b, 30) for b in blocks) |
@@ -0,0 +1,138 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | ||||
|
3 | from mercurial import minirst | |||
|
4 | ||||
|
5 | def debugformat(title, text, width): | |||
|
6 | print "%s formatted to fit within %d characters:" % (title, width) | |||
|
7 | print "-" * 70 | |||
|
8 | print minirst.format(text, width) | |||
|
9 | print "-" * 70 | |||
|
10 | ||||
|
11 | ||||
|
12 | paragraphs = """ | |||
|
13 | This is some text in the first paragraph. | |||
|
14 | ||||
|
15 | An indented paragraph | |||
|
16 | with just two lines. | |||
|
17 | ||||
|
18 | ||||
|
19 | The third paragraph. It is followed by some | |||
|
20 | random lines with spurious spaces. | |||
|
21 | ||||
|
22 | ||||
|
23 | ||||
|
24 | ||||
|
25 | ||||
|
26 | No indention | |||
|
27 | here, despite | |||
|
28 | the uneven left | |||
|
29 | margin. | |||
|
30 | ||||
|
31 | Only the | |||
|
32 | left-most line | |||
|
33 | (this line!) | |||
|
34 | is significant | |||
|
35 | for the indentation | |||
|
36 | ||||
|
37 | """ | |||
|
38 | ||||
|
39 | debugformat('paragraphs', paragraphs, 60) | |||
|
40 | debugformat('paragraphs', paragraphs, 30) | |||
|
41 | ||||
|
42 | ||||
|
43 | definitions = """ | |||
|
44 | A Term | |||
|
45 | Definition. The indented | |||
|
46 | lines make up the definition. | |||
|
47 | Another Term | |||
|
48 | Another definition. The final line in the | |||
|
49 | definition determines the indentation, so | |||
|
50 | this will be indented with four spaces. | |||
|
51 | ||||
|
52 | A Nested/Indented Term | |||
|
53 | Definition. | |||
|
54 | """ | |||
|
55 | ||||
|
56 | debugformat('definitions', definitions, 60) | |||
|
57 | debugformat('definitions', definitions, 30) | |||
|
58 | ||||
|
59 | ||||
|
60 | literals = r""" | |||
|
61 | The fully minimized form is the most | |||
|
62 | convenient form:: | |||
|
63 | ||||
|
64 | Hello | |||
|
65 | literal | |||
|
66 | world | |||
|
67 | ||||
|
68 | In the partially minimized form a paragraph | |||
|
69 | simply ends with space-double-colon. :: | |||
|
70 | ||||
|
71 | //////////////////////////////////////// | |||
|
72 | long un-wrapped line in a literal block | |||
|
73 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ | |||
|
74 | ||||
|
75 | :: | |||
|
76 | ||||
|
77 | This literal block is started with '::', | |||
|
78 | the so-called expanded form. The paragraph | |||
|
79 | with '::' disappears in the final output. | |||
|
80 | """ | |||
|
81 | ||||
|
82 | debugformat('literals', literals, 60) | |||
|
83 | debugformat('literals', literals, 30) | |||
|
84 | ||||
|
85 | ||||
|
86 | lists = """ | |||
|
87 | - This is the first list item. | |||
|
88 | ||||
|
89 | Second paragraph in the first list item. | |||
|
90 | ||||
|
91 | - List items need not be separated | |||
|
92 | by a blank line. | |||
|
93 | - And will be rendered without | |||
|
94 | one in any case. | |||
|
95 | ||||
|
96 | We can have indented lists: | |||
|
97 | ||||
|
98 | - This is an indented list item | |||
|
99 | ||||
|
100 | - Another indented list item:: | |||
|
101 | ||||
|
102 | - A literal block in the middle | |||
|
103 | of an indented list. | |||
|
104 | ||||
|
105 | (The above is not a list item since we are in the literal block.) | |||
|
106 | ||||
|
107 | :: | |||
|
108 | ||||
|
109 | Literal block with no indentation. | |||
|
110 | """ | |||
|
111 | ||||
|
112 | debugformat('lists', lists, 60) | |||
|
113 | debugformat('lists', lists, 30) | |||
|
114 | ||||
|
115 | ||||
|
116 | options = """ | |||
|
117 | There is support for simple option lists, | |||
|
118 | but only with long options: | |||
|
119 | ||||
|
120 | --all Output all. | |||
|
121 | --both Output both (this description is | |||
|
122 | quite long). | |||
|
123 | --long Output all day long. | |||
|
124 | ||||
|
125 | --par This option has two paragraphs in its description. | |||
|
126 | This is the first. | |||
|
127 | ||||
|
128 | This is the second. Blank lines may be omitted between | |||
|
129 | options (as above) or left in (as here). | |||
|
130 | ||||
|
131 | The next paragraph looks like an option list, but lacks the two-space | |||
|
132 | marker after the option. It is treated as a normal paragraph: | |||
|
133 | ||||
|
134 | --foo bar baz | |||
|
135 | """ | |||
|
136 | ||||
|
137 | debugformat('options', options, 60) | |||
|
138 | debugformat('options', options, 30) |
@@ -0,0 +1,209 b'' | |||||
|
1 | paragraphs formatted to fit within 60 characters: | |||
|
2 | ---------------------------------------------------------------------- | |||
|
3 | This is some text in the first paragraph. | |||
|
4 | ||||
|
5 | An indented paragraph with just two lines. | |||
|
6 | ||||
|
7 | The third paragraph. It is followed by some random lines | |||
|
8 | with spurious spaces. | |||
|
9 | ||||
|
10 | No indention here, despite the uneven left margin. | |||
|
11 | ||||
|
12 | Only the left-most line (this line!) is significant for | |||
|
13 | the indentation | |||
|
14 | ---------------------------------------------------------------------- | |||
|
15 | ||||
|
16 | paragraphs formatted to fit within 30 characters: | |||
|
17 | ---------------------------------------------------------------------- | |||
|
18 | This is some text in the first | |||
|
19 | paragraph. | |||
|
20 | ||||
|
21 | An indented paragraph with | |||
|
22 | just two lines. | |||
|
23 | ||||
|
24 | The third paragraph. It is | |||
|
25 | followed by some random lines | |||
|
26 | with spurious spaces. | |||
|
27 | ||||
|
28 | No indention here, despite the | |||
|
29 | uneven left margin. | |||
|
30 | ||||
|
31 | Only the left-most line | |||
|
32 | (this line!) is significant | |||
|
33 | for the indentation | |||
|
34 | ---------------------------------------------------------------------- | |||
|
35 | ||||
|
36 | definitions formatted to fit within 60 characters: | |||
|
37 | ---------------------------------------------------------------------- | |||
|
38 | A Term | |||
|
39 | Definition. The indented lines make up the definition. | |||
|
40 | Another Term | |||
|
41 | Another definition. The final line in the definition | |||
|
42 | determines the indentation, so this will be indented | |||
|
43 | with four spaces. | |||
|
44 | A Nested/Indented Term | |||
|
45 | Definition. | |||
|
46 | ---------------------------------------------------------------------- | |||
|
47 | ||||
|
48 | definitions formatted to fit within 30 characters: | |||
|
49 | ---------------------------------------------------------------------- | |||
|
50 | A Term | |||
|
51 | Definition. The indented | |||
|
52 | lines make up the | |||
|
53 | definition. | |||
|
54 | Another Term | |||
|
55 | Another definition. The | |||
|
56 | final line in the | |||
|
57 | definition determines the | |||
|
58 | indentation, so this will | |||
|
59 | be indented with four | |||
|
60 | spaces. | |||
|
61 | A Nested/Indented Term | |||
|
62 | Definition. | |||
|
63 | ---------------------------------------------------------------------- | |||
|
64 | ||||
|
65 | literals formatted to fit within 60 characters: | |||
|
66 | ---------------------------------------------------------------------- | |||
|
67 | The fully minimized form is the most convenient form: | |||
|
68 | ||||
|
69 | Hello | |||
|
70 | literal | |||
|
71 | world | |||
|
72 | ||||
|
73 | In the partially minimized form a paragraph simply ends with | |||
|
74 | space-double-colon. | |||
|
75 | ||||
|
76 | //////////////////////////////////////// | |||
|
77 | long un-wrapped line in a literal block | |||
|
78 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ | |||
|
79 | ||||
|
80 | This literal block is started with '::', | |||
|
81 | the so-called expanded form. The paragraph | |||
|
82 | with '::' disappears in the final output. | |||
|
83 | ---------------------------------------------------------------------- | |||
|
84 | ||||
|
85 | literals formatted to fit within 30 characters: | |||
|
86 | ---------------------------------------------------------------------- | |||
|
87 | The fully minimized form is | |||
|
88 | the most convenient form: | |||
|
89 | ||||
|
90 | Hello | |||
|
91 | literal | |||
|
92 | world | |||
|
93 | ||||
|
94 | In the partially minimized | |||
|
95 | form a paragraph simply ends | |||
|
96 | with space-double-colon. | |||
|
97 | ||||
|
98 | //////////////////////////////////////// | |||
|
99 | long un-wrapped line in a literal block | |||
|
100 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ | |||
|
101 | ||||
|
102 | This literal block is started with '::', | |||
|
103 | the so-called expanded form. The paragraph | |||
|
104 | with '::' disappears in the final output. | |||
|
105 | ---------------------------------------------------------------------- | |||
|
106 | ||||
|
107 | lists formatted to fit within 60 characters: | |||
|
108 | ---------------------------------------------------------------------- | |||
|
109 | - This is the first list item. | |||
|
110 | ||||
|
111 | Second paragraph in the first list item. | |||
|
112 | ||||
|
113 | - List items need not be separated by a blank line. | |||
|
114 | - And will be rendered without one in any case. | |||
|
115 | ||||
|
116 | We can have indented lists: | |||
|
117 | ||||
|
118 | - This is an indented list item | |||
|
119 | - Another indented list item: | |||
|
120 | ||||
|
121 | - A literal block in the middle | |||
|
122 | of an indented list. | |||
|
123 | ||||
|
124 | (The above is not a list item since we are in the literal block.) | |||
|
125 | ||||
|
126 | Literal block with no indentation. | |||
|
127 | ---------------------------------------------------------------------- | |||
|
128 | ||||
|
129 | lists formatted to fit within 30 characters: | |||
|
130 | ---------------------------------------------------------------------- | |||
|
131 | - This is the first list item. | |||
|
132 | ||||
|
133 | Second paragraph in the | |||
|
134 | first list item. | |||
|
135 | ||||
|
136 | - List items need not be | |||
|
137 | separated by a blank line. | |||
|
138 | - And will be rendered without | |||
|
139 | one in any case. | |||
|
140 | ||||
|
141 | We can have indented lists: | |||
|
142 | ||||
|
143 | - This is an indented list | |||
|
144 | item | |||
|
145 | - Another indented list | |||
|
146 | item: | |||
|
147 | ||||
|
148 | - A literal block in the middle | |||
|
149 | of an indented list. | |||
|
150 | ||||
|
151 | (The above is not a list item since we are in the literal block.) | |||
|
152 | ||||
|
153 | Literal block with no indentation. | |||
|
154 | ---------------------------------------------------------------------- | |||
|
155 | ||||
|
156 | options formatted to fit within 60 characters: | |||
|
157 | ---------------------------------------------------------------------- | |||
|
158 | There is support for simple option lists, but only with long | |||
|
159 | options: | |||
|
160 | ||||
|
161 | --all Output all. | |||
|
162 | --both Output both (this description is quite long). | |||
|
163 | --long Output all day long. | |||
|
164 | --par This option has two paragraphs in its | |||
|
165 | description. This is the first. | |||
|
166 | ||||
|
167 | This is the second. Blank lines may be omitted | |||
|
168 | between options (as above) or left in (as here). | |||
|
169 | ||||
|
170 | The next paragraph looks like an option list, but lacks the | |||
|
171 | two-space marker after the option. It is treated as a normal | |||
|
172 | paragraph: | |||
|
173 | ||||
|
174 | --foo bar baz | |||
|
175 | ---------------------------------------------------------------------- | |||
|
176 | ||||
|
177 | options formatted to fit within 30 characters: | |||
|
178 | ---------------------------------------------------------------------- | |||
|
179 | There is support for simple | |||
|
180 | option lists, but only with | |||
|
181 | long options: | |||
|
182 | ||||
|
183 | --all Output all. | |||
|
184 | --both Output both (this | |||
|
185 | description is | |||
|
186 | quite long). | |||
|
187 | --long Output all day | |||
|
188 | long. | |||
|
189 | --par This option has two | |||
|
190 | paragraphs in its | |||
|
191 | description. This | |||
|
192 | is the first. | |||
|
193 | ||||
|
194 | This is the second. | |||
|
195 | Blank lines may be | |||
|
196 | omitted between | |||
|
197 | options (as above) | |||
|
198 | or left in (as | |||
|
199 | here). | |||
|
200 | ||||
|
201 | The next paragraph looks like | |||
|
202 | an option list, but lacks the | |||
|
203 | two-space marker after the | |||
|
204 | option. It is treated as a | |||
|
205 | normal paragraph: | |||
|
206 | ||||
|
207 | --foo bar baz | |||
|
208 | ---------------------------------------------------------------------- | |||
|
209 |
General Comments 0
You need to be logged in to leave comments.
Login now