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