##// END OF EJS Templates
minirst: simplify and standardize field list formatting...
Olav Reinert -
r15861:ee8f5e4c default
parent child Browse files
Show More
@@ -1,687 +1,677 b''
1 # minirst.py - minimal reStructuredText parser
1 # minirst.py - minimal reStructuredText parser
2 #
2 #
3 # Copyright 2009, 2010 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2009, 2010 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """simplified reStructuredText parser.
8 """simplified reStructuredText parser.
9
9
10 This parser knows just enough about reStructuredText to parse the
10 This parser knows just enough about reStructuredText to parse the
11 Mercurial docstrings.
11 Mercurial docstrings.
12
12
13 It cheats in a major way: nested blocks are not really nested. They
13 It cheats in a major way: nested blocks are not really nested. They
14 are just indented blocks that look like they are nested. This relies
14 are just indented blocks that look like they are nested. This relies
15 on the user to keep the right indentation for the blocks.
15 on the user to keep the right indentation for the blocks.
16
16
17 Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
17 Remember to update http://mercurial.selenic.com/wiki/HelpStyleGuide
18 when adding support for new constructs.
18 when adding support for new constructs.
19 """
19 """
20
20
21 import re
21 import re
22 import util, encoding
22 import util, encoding
23 from i18n import _
23 from i18n import _
24
24
25 def replace(text, substs):
25 def replace(text, substs):
26 '''
26 '''
27 Apply a list of (find, replace) pairs to a text.
27 Apply a list of (find, replace) pairs to a text.
28
28
29 >>> replace("foo bar", [('f', 'F'), ('b', 'B')])
29 >>> replace("foo bar", [('f', 'F'), ('b', 'B')])
30 'Foo Bar'
30 'Foo Bar'
31 >>> encoding.encoding = 'latin1'
31 >>> encoding.encoding = 'latin1'
32 >>> replace('\\x81\\\\', [('\\\\', '/')])
32 >>> replace('\\x81\\\\', [('\\\\', '/')])
33 '\\x81/'
33 '\\x81/'
34 >>> encoding.encoding = 'shiftjis'
34 >>> encoding.encoding = 'shiftjis'
35 >>> replace('\\x81\\\\', [('\\\\', '/')])
35 >>> replace('\\x81\\\\', [('\\\\', '/')])
36 '\\x81\\\\'
36 '\\x81\\\\'
37 '''
37 '''
38
38
39 # some character encodings (cp932 for Japanese, at least) use
39 # some character encodings (cp932 for Japanese, at least) use
40 # ASCII characters other than control/alphabet/digit as a part of
40 # ASCII characters other than control/alphabet/digit as a part of
41 # multi-bytes characters, so direct replacing with such characters
41 # multi-bytes characters, so direct replacing with such characters
42 # on strings in local encoding causes invalid byte sequences.
42 # on strings in local encoding causes invalid byte sequences.
43 utext = text.decode(encoding.encoding)
43 utext = text.decode(encoding.encoding)
44 for f, t in substs:
44 for f, t in substs:
45 utext = utext.replace(f, t)
45 utext = utext.replace(f, t)
46 return utext.encode(encoding.encoding)
46 return utext.encode(encoding.encoding)
47
47
48 _blockre = re.compile(r"\n(?:\s*\n)+")
48 _blockre = re.compile(r"\n(?:\s*\n)+")
49
49
50 def findblocks(text):
50 def findblocks(text):
51 """Find continuous blocks of lines in text.
51 """Find continuous blocks of lines in text.
52
52
53 Returns a list of dictionaries representing the blocks. Each block
53 Returns a list of dictionaries representing the blocks. Each block
54 has an 'indent' field and a 'lines' field.
54 has an 'indent' field and a 'lines' field.
55 """
55 """
56 blocks = []
56 blocks = []
57 for b in _blockre.split(text.lstrip('\n').rstrip()):
57 for b in _blockre.split(text.lstrip('\n').rstrip()):
58 lines = b.splitlines()
58 lines = b.splitlines()
59 if lines:
59 if lines:
60 indent = min((len(l) - len(l.lstrip())) for l in lines)
60 indent = min((len(l) - len(l.lstrip())) for l in lines)
61 lines = [l[indent:] for l in lines]
61 lines = [l[indent:] for l in lines]
62 blocks.append(dict(indent=indent, lines=lines))
62 blocks.append(dict(indent=indent, lines=lines))
63 return blocks
63 return blocks
64
64
65 def findliteralblocks(blocks):
65 def findliteralblocks(blocks):
66 """Finds literal blocks and adds a 'type' field to the blocks.
66 """Finds literal blocks and adds a 'type' field to the blocks.
67
67
68 Literal blocks are given the type 'literal', all other blocks are
68 Literal blocks are given the type 'literal', all other blocks are
69 given type the 'paragraph'.
69 given type the 'paragraph'.
70 """
70 """
71 i = 0
71 i = 0
72 while i < len(blocks):
72 while i < len(blocks):
73 # Searching for a block that looks like this:
73 # Searching for a block that looks like this:
74 #
74 #
75 # +------------------------------+
75 # +------------------------------+
76 # | paragraph |
76 # | paragraph |
77 # | (ends with "::") |
77 # | (ends with "::") |
78 # +------------------------------+
78 # +------------------------------+
79 # +---------------------------+
79 # +---------------------------+
80 # | indented literal block |
80 # | indented literal block |
81 # +---------------------------+
81 # +---------------------------+
82 blocks[i]['type'] = 'paragraph'
82 blocks[i]['type'] = 'paragraph'
83 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
83 if blocks[i]['lines'][-1].endswith('::') and i + 1 < len(blocks):
84 indent = blocks[i]['indent']
84 indent = blocks[i]['indent']
85 adjustment = blocks[i + 1]['indent'] - indent
85 adjustment = blocks[i + 1]['indent'] - indent
86
86
87 if blocks[i]['lines'] == ['::']:
87 if blocks[i]['lines'] == ['::']:
88 # Expanded form: remove block
88 # Expanded form: remove block
89 del blocks[i]
89 del blocks[i]
90 i -= 1
90 i -= 1
91 elif blocks[i]['lines'][-1].endswith(' ::'):
91 elif blocks[i]['lines'][-1].endswith(' ::'):
92 # Partially minimized form: remove space and both
92 # Partially minimized form: remove space and both
93 # colons.
93 # colons.
94 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
94 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-3]
95 else:
95 else:
96 # Fully minimized form: remove just one colon.
96 # Fully minimized form: remove just one colon.
97 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
97 blocks[i]['lines'][-1] = blocks[i]['lines'][-1][:-1]
98
98
99 # List items are formatted with a hanging indent. We must
99 # List items are formatted with a hanging indent. We must
100 # correct for this here while we still have the original
100 # correct for this here while we still have the original
101 # information on the indentation of the subsequent literal
101 # information on the indentation of the subsequent literal
102 # blocks available.
102 # blocks available.
103 m = _bulletre.match(blocks[i]['lines'][0])
103 m = _bulletre.match(blocks[i]['lines'][0])
104 if m:
104 if m:
105 indent += m.end()
105 indent += m.end()
106 adjustment -= m.end()
106 adjustment -= m.end()
107
107
108 # Mark the following indented blocks.
108 # Mark the following indented blocks.
109 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
109 while i + 1 < len(blocks) and blocks[i + 1]['indent'] > indent:
110 blocks[i + 1]['type'] = 'literal'
110 blocks[i + 1]['type'] = 'literal'
111 blocks[i + 1]['indent'] -= adjustment
111 blocks[i + 1]['indent'] -= adjustment
112 i += 1
112 i += 1
113 i += 1
113 i += 1
114 return blocks
114 return blocks
115
115
116 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
116 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)|\|) ')
117 _optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
117 _optionre = re.compile(r'^(-([a-zA-Z0-9]), )?(--[a-z0-9-]+)'
118 r'((.*) +)(.*)$')
118 r'((.*) +)(.*)$')
119 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
119 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)')
120 _definitionre = re.compile(r'[^ ]')
120 _definitionre = re.compile(r'[^ ]')
121 _tablere = re.compile(r'(=+\s+)*=+')
121 _tablere = re.compile(r'(=+\s+)*=+')
122
122
123 def splitparagraphs(blocks):
123 def splitparagraphs(blocks):
124 """Split paragraphs into lists."""
124 """Split paragraphs into lists."""
125 # Tuples with (list type, item regexp, single line items?). Order
125 # Tuples with (list type, item regexp, single line items?). Order
126 # matters: definition lists has the least specific regexp and must
126 # matters: definition lists has the least specific regexp and must
127 # come last.
127 # come last.
128 listtypes = [('bullet', _bulletre, True),
128 listtypes = [('bullet', _bulletre, True),
129 ('option', _optionre, True),
129 ('option', _optionre, True),
130 ('field', _fieldre, True),
130 ('field', _fieldre, True),
131 ('definition', _definitionre, False)]
131 ('definition', _definitionre, False)]
132
132
133 def match(lines, i, itemre, singleline):
133 def match(lines, i, itemre, singleline):
134 """Does itemre match an item at line i?
134 """Does itemre match an item at line i?
135
135
136 A list item can be followed by an idented line or another list
136 A list item can be followed by an idented line or another list
137 item (but only if singleline is True).
137 item (but only if singleline is True).
138 """
138 """
139 line1 = lines[i]
139 line1 = lines[i]
140 line2 = i + 1 < len(lines) and lines[i + 1] or ''
140 line2 = i + 1 < len(lines) and lines[i + 1] or ''
141 if not itemre.match(line1):
141 if not itemre.match(line1):
142 return False
142 return False
143 if singleline:
143 if singleline:
144 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
144 return line2 == '' or line2[0] == ' ' or itemre.match(line2)
145 else:
145 else:
146 return line2.startswith(' ')
146 return line2.startswith(' ')
147
147
148 i = 0
148 i = 0
149 while i < len(blocks):
149 while i < len(blocks):
150 if blocks[i]['type'] == 'paragraph':
150 if blocks[i]['type'] == 'paragraph':
151 lines = blocks[i]['lines']
151 lines = blocks[i]['lines']
152 for type, itemre, singleline in listtypes:
152 for type, itemre, singleline in listtypes:
153 if match(lines, 0, itemre, singleline):
153 if match(lines, 0, itemre, singleline):
154 items = []
154 items = []
155 for j, line in enumerate(lines):
155 for j, line in enumerate(lines):
156 if match(lines, j, itemre, singleline):
156 if match(lines, j, itemre, singleline):
157 items.append(dict(type=type, lines=[],
157 items.append(dict(type=type, lines=[],
158 indent=blocks[i]['indent']))
158 indent=blocks[i]['indent']))
159 items[-1]['lines'].append(line)
159 items[-1]['lines'].append(line)
160 blocks[i:i + 1] = items
160 blocks[i:i + 1] = items
161 break
161 break
162 i += 1
162 i += 1
163 return blocks
163 return blocks
164
164
165 _fieldwidth = 12
165 _fieldwidth = 14
166
166
167 def updatefieldlists(blocks):
167 def updatefieldlists(blocks):
168 """Find key and maximum key width for field lists."""
168 """Find key for field lists."""
169 i = 0
169 i = 0
170 while i < len(blocks):
170 while i < len(blocks):
171 if blocks[i]['type'] != 'field':
171 if blocks[i]['type'] != 'field':
172 i += 1
172 i += 1
173 continue
173 continue
174
174
175 keywidth = 0
176 j = i
175 j = i
177 while j < len(blocks) and blocks[j]['type'] == 'field':
176 while j < len(blocks) and blocks[j]['type'] == 'field':
178 m = _fieldre.match(blocks[j]['lines'][0])
177 m = _fieldre.match(blocks[j]['lines'][0])
179 key, rest = m.groups()
178 key, rest = m.groups()
180 blocks[j]['lines'][0] = rest
179 blocks[j]['lines'][0] = rest
181 blocks[j]['key'] = key
180 blocks[j]['key'] = key
182 keywidth = max(keywidth, len(key))
183 j += 1
181 j += 1
184
182
185 for block in blocks[i:j]:
186 block['keywidth'] = keywidth
187 i = j + 1
183 i = j + 1
188
184
189 return blocks
185 return blocks
190
186
191 def updateoptionlists(blocks):
187 def updateoptionlists(blocks):
192 i = 0
188 i = 0
193 while i < len(blocks):
189 while i < len(blocks):
194 if blocks[i]['type'] != 'option':
190 if blocks[i]['type'] != 'option':
195 i += 1
191 i += 1
196 continue
192 continue
197
193
198 optstrwidth = 0
194 optstrwidth = 0
199 j = i
195 j = i
200 while j < len(blocks) and blocks[j]['type'] == 'option':
196 while j < len(blocks) and blocks[j]['type'] == 'option':
201 m = _optionre.match(blocks[j]['lines'][0])
197 m = _optionre.match(blocks[j]['lines'][0])
202
198
203 shortoption = m.group(2)
199 shortoption = m.group(2)
204 group3 = m.group(3)
200 group3 = m.group(3)
205 longoption = group3[2:].strip()
201 longoption = group3[2:].strip()
206 desc = m.group(6).strip()
202 desc = m.group(6).strip()
207 longoptionarg = m.group(5).strip()
203 longoptionarg = m.group(5).strip()
208 blocks[j]['lines'][0] = desc
204 blocks[j]['lines'][0] = desc
209
205
210 noshortop = ''
206 noshortop = ''
211 if not shortoption:
207 if not shortoption:
212 noshortop = ' '
208 noshortop = ' '
213
209
214 opt = "%s%s" % (shortoption and "-%s " % shortoption or '',
210 opt = "%s%s" % (shortoption and "-%s " % shortoption or '',
215 ("%s--%s %s") % (noshortop, longoption,
211 ("%s--%s %s") % (noshortop, longoption,
216 longoptionarg))
212 longoptionarg))
217 opt = opt.rstrip()
213 opt = opt.rstrip()
218 blocks[j]['optstr'] = opt
214 blocks[j]['optstr'] = opt
219 optstrwidth = max(optstrwidth, encoding.colwidth(opt))
215 optstrwidth = max(optstrwidth, encoding.colwidth(opt))
220 j += 1
216 j += 1
221
217
222 for block in blocks[i:j]:
218 for block in blocks[i:j]:
223 block['optstrwidth'] = optstrwidth
219 block['optstrwidth'] = optstrwidth
224 i = j + 1
220 i = j + 1
225 return blocks
221 return blocks
226
222
227 def prunecontainers(blocks, keep):
223 def prunecontainers(blocks, keep):
228 """Prune unwanted containers.
224 """Prune unwanted containers.
229
225
230 The blocks must have a 'type' field, i.e., they should have been
226 The blocks must have a 'type' field, i.e., they should have been
231 run through findliteralblocks first.
227 run through findliteralblocks first.
232 """
228 """
233 pruned = []
229 pruned = []
234 i = 0
230 i = 0
235 while i + 1 < len(blocks):
231 while i + 1 < len(blocks):
236 # Searching for a block that looks like this:
232 # Searching for a block that looks like this:
237 #
233 #
238 # +-------+---------------------------+
234 # +-------+---------------------------+
239 # | ".. container ::" type |
235 # | ".. container ::" type |
240 # +---+ |
236 # +---+ |
241 # | blocks |
237 # | blocks |
242 # +-------------------------------+
238 # +-------------------------------+
243 if (blocks[i]['type'] == 'paragraph' and
239 if (blocks[i]['type'] == 'paragraph' and
244 blocks[i]['lines'][0].startswith('.. container::')):
240 blocks[i]['lines'][0].startswith('.. container::')):
245 indent = blocks[i]['indent']
241 indent = blocks[i]['indent']
246 adjustment = blocks[i + 1]['indent'] - indent
242 adjustment = blocks[i + 1]['indent'] - indent
247 containertype = blocks[i]['lines'][0][15:]
243 containertype = blocks[i]['lines'][0][15:]
248 prune = containertype not in keep
244 prune = containertype not in keep
249 if prune:
245 if prune:
250 pruned.append(containertype)
246 pruned.append(containertype)
251
247
252 # Always delete "..container:: type" block
248 # Always delete "..container:: type" block
253 del blocks[i]
249 del blocks[i]
254 j = i
250 j = i
255 i -= 1
251 i -= 1
256 while j < len(blocks) and blocks[j]['indent'] > indent:
252 while j < len(blocks) and blocks[j]['indent'] > indent:
257 if prune:
253 if prune:
258 del blocks[j]
254 del blocks[j]
259 else:
255 else:
260 blocks[j]['indent'] -= adjustment
256 blocks[j]['indent'] -= adjustment
261 j += 1
257 j += 1
262 i += 1
258 i += 1
263 return blocks, pruned
259 return blocks, pruned
264
260
265 _sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
261 _sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
266
262
267 def findtables(blocks):
263 def findtables(blocks):
268 '''Find simple tables
264 '''Find simple tables
269
265
270 Only simple one-line table elements are supported
266 Only simple one-line table elements are supported
271 '''
267 '''
272
268
273 for block in blocks:
269 for block in blocks:
274 # Searching for a block that looks like this:
270 # Searching for a block that looks like this:
275 #
271 #
276 # === ==== ===
272 # === ==== ===
277 # A B C
273 # A B C
278 # === ==== === <- optional
274 # === ==== === <- optional
279 # 1 2 3
275 # 1 2 3
280 # x y z
276 # x y z
281 # === ==== ===
277 # === ==== ===
282 if (block['type'] == 'paragraph' and
278 if (block['type'] == 'paragraph' and
283 len(block['lines']) > 2 and
279 len(block['lines']) > 2 and
284 _tablere.match(block['lines'][0]) and
280 _tablere.match(block['lines'][0]) and
285 block['lines'][0] == block['lines'][-1]):
281 block['lines'][0] == block['lines'][-1]):
286 block['type'] = 'table'
282 block['type'] = 'table'
287 block['header'] = False
283 block['header'] = False
288 div = block['lines'][0]
284 div = block['lines'][0]
289
285
290 # column markers are ASCII so we can calculate column
286 # column markers are ASCII so we can calculate column
291 # position in bytes
287 # position in bytes
292 columns = [x for x in xrange(len(div))
288 columns = [x for x in xrange(len(div))
293 if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
289 if div[x] == '=' and (x == 0 or div[x - 1] == ' ')]
294 rows = []
290 rows = []
295 for l in block['lines'][1:-1]:
291 for l in block['lines'][1:-1]:
296 if l == div:
292 if l == div:
297 block['header'] = True
293 block['header'] = True
298 continue
294 continue
299 row = []
295 row = []
300 # we measure columns not in bytes or characters but in
296 # we measure columns not in bytes or characters but in
301 # colwidth which makes things tricky
297 # colwidth which makes things tricky
302 pos = columns[0] # leading whitespace is bytes
298 pos = columns[0] # leading whitespace is bytes
303 for n, start in enumerate(columns):
299 for n, start in enumerate(columns):
304 if n + 1 < len(columns):
300 if n + 1 < len(columns):
305 width = columns[n + 1] - start
301 width = columns[n + 1] - start
306 v = encoding.getcols(l, pos, width) # gather columns
302 v = encoding.getcols(l, pos, width) # gather columns
307 pos += len(v) # calculate byte position of end
303 pos += len(v) # calculate byte position of end
308 row.append(v.strip())
304 row.append(v.strip())
309 else:
305 else:
310 row.append(l[pos:].strip())
306 row.append(l[pos:].strip())
311 rows.append(row)
307 rows.append(row)
312
308
313 block['table'] = rows
309 block['table'] = rows
314
310
315 return blocks
311 return blocks
316
312
317 def findsections(blocks):
313 def findsections(blocks):
318 """Finds sections.
314 """Finds sections.
319
315
320 The blocks must have a 'type' field, i.e., they should have been
316 The blocks must have a 'type' field, i.e., they should have been
321 run through findliteralblocks first.
317 run through findliteralblocks first.
322 """
318 """
323 for block in blocks:
319 for block in blocks:
324 # Searching for a block that looks like this:
320 # Searching for a block that looks like this:
325 #
321 #
326 # +------------------------------+
322 # +------------------------------+
327 # | Section title |
323 # | Section title |
328 # | ------------- |
324 # | ------------- |
329 # +------------------------------+
325 # +------------------------------+
330 if (block['type'] == 'paragraph' and
326 if (block['type'] == 'paragraph' and
331 len(block['lines']) == 2 and
327 len(block['lines']) == 2 and
332 encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
328 encoding.colwidth(block['lines'][0]) == len(block['lines'][1]) and
333 _sectionre.match(block['lines'][1])):
329 _sectionre.match(block['lines'][1])):
334 block['underline'] = block['lines'][1][0]
330 block['underline'] = block['lines'][1][0]
335 block['type'] = 'section'
331 block['type'] = 'section'
336 del block['lines'][1]
332 del block['lines'][1]
337 return blocks
333 return blocks
338
334
339 def inlineliterals(blocks):
335 def inlineliterals(blocks):
340 substs = [('``', '"')]
336 substs = [('``', '"')]
341 for b in blocks:
337 for b in blocks:
342 if b['type'] in ('paragraph', 'section'):
338 if b['type'] in ('paragraph', 'section'):
343 b['lines'] = [replace(l, substs) for l in b['lines']]
339 b['lines'] = [replace(l, substs) for l in b['lines']]
344 return blocks
340 return blocks
345
341
346 def hgrole(blocks):
342 def hgrole(blocks):
347 substs = [(':hg:`', '"hg '), ('`', '"')]
343 substs = [(':hg:`', '"hg '), ('`', '"')]
348 for b in blocks:
344 for b in blocks:
349 if b['type'] in ('paragraph', 'section'):
345 if b['type'] in ('paragraph', 'section'):
350 # Turn :hg:`command` into "hg command". This also works
346 # Turn :hg:`command` into "hg command". This also works
351 # when there is a line break in the command and relies on
347 # when there is a line break in the command and relies on
352 # the fact that we have no stray back-quotes in the input
348 # the fact that we have no stray back-quotes in the input
353 # (run the blocks through inlineliterals first).
349 # (run the blocks through inlineliterals first).
354 b['lines'] = [replace(l, substs) for l in b['lines']]
350 b['lines'] = [replace(l, substs) for l in b['lines']]
355 return blocks
351 return blocks
356
352
357 def addmargins(blocks):
353 def addmargins(blocks):
358 """Adds empty blocks for vertical spacing.
354 """Adds empty blocks for vertical spacing.
359
355
360 This groups bullets, options, and definitions together with no vertical
356 This groups bullets, options, and definitions together with no vertical
361 space between them, and adds an empty block between all other blocks.
357 space between them, and adds an empty block between all other blocks.
362 """
358 """
363 i = 1
359 i = 1
364 while i < len(blocks):
360 while i < len(blocks):
365 if (blocks[i]['type'] == blocks[i - 1]['type'] and
361 if (blocks[i]['type'] == blocks[i - 1]['type'] and
366 blocks[i]['type'] in ('bullet', 'option', 'field')):
362 blocks[i]['type'] in ('bullet', 'option', 'field')):
367 i += 1
363 i += 1
368 else:
364 else:
369 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
365 blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
370 i += 2
366 i += 2
371 return blocks
367 return blocks
372
368
373 def prunecomments(blocks):
369 def prunecomments(blocks):
374 """Remove comments."""
370 """Remove comments."""
375 i = 0
371 i = 0
376 while i < len(blocks):
372 while i < len(blocks):
377 b = blocks[i]
373 b = blocks[i]
378 if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
374 if b['type'] == 'paragraph' and (b['lines'][0].startswith('.. ') or
379 b['lines'] == ['..']):
375 b['lines'] == ['..']):
380 del blocks[i]
376 del blocks[i]
381 if i < len(blocks) and blocks[i]['type'] == 'margin':
377 if i < len(blocks) and blocks[i]['type'] == 'margin':
382 del blocks[i]
378 del blocks[i]
383 else:
379 else:
384 i += 1
380 i += 1
385 return blocks
381 return blocks
386
382
387 _admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
383 _admonitionre = re.compile(r"\.\. (admonition|attention|caution|danger|"
388 r"error|hint|important|note|tip|warning)::",
384 r"error|hint|important|note|tip|warning)::",
389 flags=re.IGNORECASE)
385 flags=re.IGNORECASE)
390
386
391 def findadmonitions(blocks):
387 def findadmonitions(blocks):
392 """
388 """
393 Makes the type of the block an admonition block if
389 Makes the type of the block an admonition block if
394 the first line is an admonition directive
390 the first line is an admonition directive
395 """
391 """
396 i = 0
392 i = 0
397 while i < len(blocks):
393 while i < len(blocks):
398 m = _admonitionre.match(blocks[i]['lines'][0])
394 m = _admonitionre.match(blocks[i]['lines'][0])
399 if m:
395 if m:
400 blocks[i]['type'] = 'admonition'
396 blocks[i]['type'] = 'admonition'
401 admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
397 admonitiontitle = blocks[i]['lines'][0][3:m.end() - 2].lower()
402
398
403 firstline = blocks[i]['lines'][0][m.end() + 1:]
399 firstline = blocks[i]['lines'][0][m.end() + 1:]
404 if firstline:
400 if firstline:
405 blocks[i]['lines'].insert(1, ' ' + firstline)
401 blocks[i]['lines'].insert(1, ' ' + firstline)
406
402
407 blocks[i]['admonitiontitle'] = admonitiontitle
403 blocks[i]['admonitiontitle'] = admonitiontitle
408 del blocks[i]['lines'][0]
404 del blocks[i]['lines'][0]
409 i = i + 1
405 i = i + 1
410 return blocks
406 return blocks
411
407
412 _admonitiontitles = {'attention': _('Attention:'),
408 _admonitiontitles = {'attention': _('Attention:'),
413 'caution': _('Caution:'),
409 'caution': _('Caution:'),
414 'danger': _('!Danger!') ,
410 'danger': _('!Danger!') ,
415 'error': _('Error:'),
411 'error': _('Error:'),
416 'hint': _('Hint:'),
412 'hint': _('Hint:'),
417 'important': _('Important:'),
413 'important': _('Important:'),
418 'note': _('Note:'),
414 'note': _('Note:'),
419 'tip': _('Tip:'),
415 'tip': _('Tip:'),
420 'warning': _('Warning!')}
416 'warning': _('Warning!')}
421
417
422 def formatoption(block, width):
418 def formatoption(block, width):
423 desc = ' '.join(map(str.strip, block['lines']))
419 desc = ' '.join(map(str.strip, block['lines']))
424 colwidth = encoding.colwidth(block['optstr'])
420 colwidth = encoding.colwidth(block['optstr'])
425 usablewidth = width - 1
421 usablewidth = width - 1
426 hanging = block['optstrwidth']
422 hanging = block['optstrwidth']
427 initindent = '%s%s ' % (block['optstr'], ' ' * ((hanging - colwidth)))
423 initindent = '%s%s ' % (block['optstr'], ' ' * ((hanging - colwidth)))
428 hangindent = ' ' * (encoding.colwidth(initindent) + 1)
424 hangindent = ' ' * (encoding.colwidth(initindent) + 1)
429 return ' %s\n' % (util.wrap(desc, usablewidth,
425 return ' %s\n' % (util.wrap(desc, usablewidth,
430 initindent=initindent,
426 initindent=initindent,
431 hangindent=hangindent))
427 hangindent=hangindent))
432
428
433 def formatblock(block, width):
429 def formatblock(block, width):
434 """Format a block according to width."""
430 """Format a block according to width."""
435 if width <= 0:
431 if width <= 0:
436 width = 78
432 width = 78
437 indent = ' ' * block['indent']
433 indent = ' ' * block['indent']
438 if block['type'] == 'admonition':
434 if block['type'] == 'admonition':
439 admonition = _admonitiontitles[block['admonitiontitle']]
435 admonition = _admonitiontitles[block['admonitiontitle']]
440 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
436 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
441
437
442 defindent = indent + hang * ' '
438 defindent = indent + hang * ' '
443 text = ' '.join(map(str.strip, block['lines']))
439 text = ' '.join(map(str.strip, block['lines']))
444 return '%s\n%s\n' % (indent + admonition,
440 return '%s\n%s\n' % (indent + admonition,
445 util.wrap(text, width=width,
441 util.wrap(text, width=width,
446 initindent=defindent,
442 initindent=defindent,
447 hangindent=defindent))
443 hangindent=defindent))
448 if block['type'] == 'margin':
444 if block['type'] == 'margin':
449 return '\n'
445 return '\n'
450 if block['type'] == 'literal':
446 if block['type'] == 'literal':
451 indent += ' '
447 indent += ' '
452 return indent + ('\n' + indent).join(block['lines']) + '\n'
448 return indent + ('\n' + indent).join(block['lines']) + '\n'
453 if block['type'] == 'section':
449 if block['type'] == 'section':
454 underline = encoding.colwidth(block['lines'][0]) * block['underline']
450 underline = encoding.colwidth(block['lines'][0]) * block['underline']
455 return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
451 return "%s%s\n%s%s\n" % (indent, block['lines'][0],indent, underline)
456 if block['type'] == 'table':
452 if block['type'] == 'table':
457 table = block['table']
453 table = block['table']
458 # compute column widths
454 # compute column widths
459 widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
455 widths = [max([encoding.colwidth(e) for e in c]) for c in zip(*table)]
460 text = ''
456 text = ''
461 span = sum(widths) + len(widths) - 1
457 span = sum(widths) + len(widths) - 1
462 indent = ' ' * block['indent']
458 indent = ' ' * block['indent']
463 hang = ' ' * (len(indent) + span - widths[-1])
459 hang = ' ' * (len(indent) + span - widths[-1])
464
460
465 for row in table:
461 for row in table:
466 l = []
462 l = []
467 for w, v in zip(widths, row):
463 for w, v in zip(widths, row):
468 pad = ' ' * (w - encoding.colwidth(v))
464 pad = ' ' * (w - encoding.colwidth(v))
469 l.append(v + pad)
465 l.append(v + pad)
470 l = ' '.join(l)
466 l = ' '.join(l)
471 l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
467 l = util.wrap(l, width=width, initindent=indent, hangindent=hang)
472 if not text and block['header']:
468 if not text and block['header']:
473 text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
469 text = l + '\n' + indent + '-' * (min(width, span)) + '\n'
474 else:
470 else:
475 text += l + "\n"
471 text += l + "\n"
476 return text
472 return text
477 if block['type'] == 'definition':
473 if block['type'] == 'definition':
478 term = indent + block['lines'][0]
474 term = indent + block['lines'][0]
479 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
475 hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
480 defindent = indent + hang * ' '
476 defindent = indent + hang * ' '
481 text = ' '.join(map(str.strip, block['lines'][1:]))
477 text = ' '.join(map(str.strip, block['lines'][1:]))
482 return '%s\n%s\n' % (term, util.wrap(text, width=width,
478 return '%s\n%s\n' % (term, util.wrap(text, width=width,
483 initindent=defindent,
479 initindent=defindent,
484 hangindent=defindent))
480 hangindent=defindent))
485 subindent = indent
481 subindent = indent
486 if block['type'] == 'bullet':
482 if block['type'] == 'bullet':
487 if block['lines'][0].startswith('| '):
483 if block['lines'][0].startswith('| '):
488 # Remove bullet for line blocks and add no extra
484 # Remove bullet for line blocks and add no extra
489 # indention.
485 # indention.
490 block['lines'][0] = block['lines'][0][2:]
486 block['lines'][0] = block['lines'][0][2:]
491 else:
487 else:
492 m = _bulletre.match(block['lines'][0])
488 m = _bulletre.match(block['lines'][0])
493 subindent = indent + m.end() * ' '
489 subindent = indent + m.end() * ' '
494 elif block['type'] == 'field':
490 elif block['type'] == 'field':
495 keywidth = block['keywidth']
496 key = block['key']
491 key = block['key']
497
498 subindent = indent + _fieldwidth * ' '
492 subindent = indent + _fieldwidth * ' '
499 if len(key) + 2 > _fieldwidth:
493 if len(key) + 2 > _fieldwidth:
500 # key too large, use full line width
494 # key too large, use full line width
501 key = key.ljust(width)
495 key = key.ljust(width)
502 elif keywidth + 2 < _fieldwidth:
503 # all keys are small, add only two spaces
504 key = key.ljust(keywidth + 2)
505 subindent = indent + (keywidth + 2) * ' '
506 else:
496 else:
507 # mixed sizes, use fieldwidth for this one
497 # key fits within field width
508 key = key.ljust(_fieldwidth)
498 key = key.ljust(_fieldwidth)
509 block['lines'][0] = key + block['lines'][0]
499 block['lines'][0] = key + block['lines'][0]
510 elif block['type'] == 'option':
500 elif block['type'] == 'option':
511 return formatoption(block, width)
501 return formatoption(block, width)
512
502
513 text = ' '.join(map(str.strip, block['lines']))
503 text = ' '.join(map(str.strip, block['lines']))
514 return util.wrap(text, width=width,
504 return util.wrap(text, width=width,
515 initindent=indent,
505 initindent=indent,
516 hangindent=subindent) + '\n'
506 hangindent=subindent) + '\n'
517
507
518 def formathtml(blocks):
508 def formathtml(blocks):
519 """Format RST blocks as HTML"""
509 """Format RST blocks as HTML"""
520
510
521 out = []
511 out = []
522 headernest = ''
512 headernest = ''
523 listnest = []
513 listnest = []
524
514
525 def openlist(start, level):
515 def openlist(start, level):
526 if not listnest or listnest[-1][0] != start:
516 if not listnest or listnest[-1][0] != start:
527 listnest.append((start, level))
517 listnest.append((start, level))
528 out.append('<%s>\n' % start)
518 out.append('<%s>\n' % start)
529
519
530 blocks = [b for b in blocks if b['type'] != 'margin']
520 blocks = [b for b in blocks if b['type'] != 'margin']
531
521
532 for pos, b in enumerate(blocks):
522 for pos, b in enumerate(blocks):
533 btype = b['type']
523 btype = b['type']
534 level = b['indent']
524 level = b['indent']
535 lines = b['lines']
525 lines = b['lines']
536
526
537 if btype == 'admonition':
527 if btype == 'admonition':
538 admonition = _admonitiontitles[b['admonitiontitle']]
528 admonition = _admonitiontitles[b['admonitiontitle']]
539 text = ' '.join(map(str.strip, lines))
529 text = ' '.join(map(str.strip, lines))
540 out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
530 out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
541 elif btype == 'paragraph':
531 elif btype == 'paragraph':
542 out.append('<p>\n%s\n</p>\n' % '\n'.join(lines))
532 out.append('<p>\n%s\n</p>\n' % '\n'.join(lines))
543 elif btype == 'margin':
533 elif btype == 'margin':
544 pass
534 pass
545 elif btype == 'literal':
535 elif btype == 'literal':
546 out.append('<pre>\n%s\n</pre>\n' % '\n'.join(lines))
536 out.append('<pre>\n%s\n</pre>\n' % '\n'.join(lines))
547 elif btype == 'section':
537 elif btype == 'section':
548 i = b['underline']
538 i = b['underline']
549 if i not in headernest:
539 if i not in headernest:
550 headernest += i
540 headernest += i
551 level = headernest.index(i) + 1
541 level = headernest.index(i) + 1
552 out.append('<h%d>%s</h%d>\n' % (level, lines[0], level))
542 out.append('<h%d>%s</h%d>\n' % (level, lines[0], level))
553 elif btype == 'table':
543 elif btype == 'table':
554 table = b['table']
544 table = b['table']
555 t = []
545 t = []
556 for row in table:
546 for row in table:
557 l = []
547 l = []
558 for v in zip(row):
548 for v in zip(row):
559 if not t:
549 if not t:
560 l.append('<th>%s</th>' % v)
550 l.append('<th>%s</th>' % v)
561 else:
551 else:
562 l.append('<td>%s</td>' % v)
552 l.append('<td>%s</td>' % v)
563 t.append(' <tr>%s</tr>\n' % ''.join(l))
553 t.append(' <tr>%s</tr>\n' % ''.join(l))
564 out.append('<table>\n%s</table>\n' % ''.join(t))
554 out.append('<table>\n%s</table>\n' % ''.join(t))
565 elif btype == 'definition':
555 elif btype == 'definition':
566 openlist('dl', level)
556 openlist('dl', level)
567 term = lines[0]
557 term = lines[0]
568 text = ' '.join(map(str.strip, lines[1:]))
558 text = ' '.join(map(str.strip, lines[1:]))
569 out.append(' <dt>%s\n <dd>%s\n' % (term, text))
559 out.append(' <dt>%s\n <dd>%s\n' % (term, text))
570 elif btype == 'bullet':
560 elif btype == 'bullet':
571 bullet, head = lines[0].split(' ', 1)
561 bullet, head = lines[0].split(' ', 1)
572 if bullet == '-':
562 if bullet == '-':
573 openlist('ul', level)
563 openlist('ul', level)
574 else:
564 else:
575 openlist('ol', level)
565 openlist('ol', level)
576 out.append(' <li> %s\n' % ' '.join([head] + lines[1:]))
566 out.append(' <li> %s\n' % ' '.join([head] + lines[1:]))
577 elif btype == 'field':
567 elif btype == 'field':
578 openlist('dl', level)
568 openlist('dl', level)
579 key = b['key']
569 key = b['key']
580 text = ' '.join(map(str.strip, lines))
570 text = ' '.join(map(str.strip, lines))
581 out.append(' <dt>%s\n <dd>%s\n' % (key, text))
571 out.append(' <dt>%s\n <dd>%s\n' % (key, text))
582 elif btype == 'option':
572 elif btype == 'option':
583 openlist('dl', level)
573 openlist('dl', level)
584 opt = b['optstr']
574 opt = b['optstr']
585 desc = ' '.join(map(str.strip, lines))
575 desc = ' '.join(map(str.strip, lines))
586 out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
576 out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
587
577
588 # close lists if indent level of next block is lower
578 # close lists if indent level of next block is lower
589 if listnest:
579 if listnest:
590 start, level = listnest[-1]
580 start, level = listnest[-1]
591 if pos == len(blocks) - 1:
581 if pos == len(blocks) - 1:
592 out.append('</%s>\n' % start)
582 out.append('</%s>\n' % start)
593 listnest.pop()
583 listnest.pop()
594 else:
584 else:
595 nb = blocks[pos + 1]
585 nb = blocks[pos + 1]
596 ni = nb['indent']
586 ni = nb['indent']
597 if (ni < level or
587 if (ni < level or
598 (ni == level and
588 (ni == level and
599 nb['type'] not in 'definition bullet field option')):
589 nb['type'] not in 'definition bullet field option')):
600 out.append('</%s>\n' % start)
590 out.append('</%s>\n' % start)
601 listnest.pop()
591 listnest.pop()
602
592
603 return ''.join(out)
593 return ''.join(out)
604
594
605 def parse(text, indent=0, keep=None):
595 def parse(text, indent=0, keep=None):
606 """Parse text into a list of blocks"""
596 """Parse text into a list of blocks"""
607 pruned = []
597 pruned = []
608 blocks = findblocks(text)
598 blocks = findblocks(text)
609 for b in blocks:
599 for b in blocks:
610 b['indent'] += indent
600 b['indent'] += indent
611 blocks = findliteralblocks(blocks)
601 blocks = findliteralblocks(blocks)
612 blocks = findtables(blocks)
602 blocks = findtables(blocks)
613 blocks, pruned = prunecontainers(blocks, keep or [])
603 blocks, pruned = prunecontainers(blocks, keep or [])
614 blocks = findsections(blocks)
604 blocks = findsections(blocks)
615 blocks = inlineliterals(blocks)
605 blocks = inlineliterals(blocks)
616 blocks = hgrole(blocks)
606 blocks = hgrole(blocks)
617 blocks = splitparagraphs(blocks)
607 blocks = splitparagraphs(blocks)
618 blocks = updatefieldlists(blocks)
608 blocks = updatefieldlists(blocks)
619 blocks = updateoptionlists(blocks)
609 blocks = updateoptionlists(blocks)
620 blocks = addmargins(blocks)
610 blocks = addmargins(blocks)
621 blocks = prunecomments(blocks)
611 blocks = prunecomments(blocks)
622 blocks = findadmonitions(blocks)
612 blocks = findadmonitions(blocks)
623 return blocks, pruned
613 return blocks, pruned
624
614
625 def formatblocks(blocks, width):
615 def formatblocks(blocks, width):
626 text = ''.join(formatblock(b, width) for b in blocks)
616 text = ''.join(formatblock(b, width) for b in blocks)
627 return text
617 return text
628
618
629 def format(text, width=80, indent=0, keep=None, style='plain'):
619 def format(text, width=80, indent=0, keep=None, style='plain'):
630 """Parse and format the text according to width."""
620 """Parse and format the text according to width."""
631 blocks, pruned = parse(text, indent, keep or [])
621 blocks, pruned = parse(text, indent, keep or [])
632 if style == 'html':
622 if style == 'html':
633 text = formathtml(blocks)
623 text = formathtml(blocks)
634 else:
624 else:
635 text = ''.join(formatblock(b, width) for b in blocks)
625 text = ''.join(formatblock(b, width) for b in blocks)
636 if keep is None:
626 if keep is None:
637 return text
627 return text
638 else:
628 else:
639 return text, pruned
629 return text, pruned
640
630
641 def getsections(blocks):
631 def getsections(blocks):
642 '''return a list of (section name, nesting level, blocks) tuples'''
632 '''return a list of (section name, nesting level, blocks) tuples'''
643 nest = ""
633 nest = ""
644 level = 0
634 level = 0
645 secs = []
635 secs = []
646 for b in blocks:
636 for b in blocks:
647 if b['type'] == 'section':
637 if b['type'] == 'section':
648 i = b['underline']
638 i = b['underline']
649 if i not in nest:
639 if i not in nest:
650 nest += i
640 nest += i
651 level = nest.index(i) + 1
641 level = nest.index(i) + 1
652 nest = nest[:level]
642 nest = nest[:level]
653 secs.append((b['lines'][0], level, [b]))
643 secs.append((b['lines'][0], level, [b]))
654 else:
644 else:
655 if not secs:
645 if not secs:
656 # add an initial empty section
646 # add an initial empty section
657 secs = [('', 0, [])]
647 secs = [('', 0, [])]
658 secs[-1][2].append(b)
648 secs[-1][2].append(b)
659 return secs
649 return secs
660
650
661 def decorateblocks(blocks, width):
651 def decorateblocks(blocks, width):
662 '''generate a list of (section name, line text) pairs for search'''
652 '''generate a list of (section name, line text) pairs for search'''
663 lines = []
653 lines = []
664 for s in getsections(blocks):
654 for s in getsections(blocks):
665 section = s[0]
655 section = s[0]
666 text = formatblocks(s[2], width)
656 text = formatblocks(s[2], width)
667 lines.append([(section, l) for l in text.splitlines(True)])
657 lines.append([(section, l) for l in text.splitlines(True)])
668 return lines
658 return lines
669
659
670 def maketable(data, indent=0, header=False):
660 def maketable(data, indent=0, header=False):
671 '''Generate an RST table for the given table data'''
661 '''Generate an RST table for the given table data'''
672
662
673 widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
663 widths = [max(encoding.colwidth(e) for e in c) for c in zip(*data)]
674 indent = ' ' * indent
664 indent = ' ' * indent
675 div = indent + ' '.join('=' * w for w in widths) + '\n'
665 div = indent + ' '.join('=' * w for w in widths) + '\n'
676
666
677 out = [div]
667 out = [div]
678 for row in data:
668 for row in data:
679 l = []
669 l = []
680 for w, v in zip(widths, row):
670 for w, v in zip(widths, row):
681 pad = ' ' * (w - encoding.colwidth(v))
671 pad = ' ' * (w - encoding.colwidth(v))
682 l.append(v + pad)
672 l.append(v + pad)
683 out.append(indent + ' '.join(l) + "\n")
673 out.append(indent + ' '.join(l) + "\n")
684 if header and len(data) > 1:
674 if header and len(data) > 1:
685 out.insert(2, div)
675 out.insert(2, div)
686 out.append(div)
676 out.append(div)
687 return ''.join(out)
677 return ''.join(out)
@@ -1,393 +1,395 b''
1 $ "$TESTDIR/hghave" unix-permissions || exit 80
1 $ "$TESTDIR/hghave" unix-permissions || exit 80
2
2
3 $ cat >> $HGRCPATH <<EOF
3 $ cat >> $HGRCPATH <<EOF
4 > [extensions]
4 > [extensions]
5 > convert=
5 > convert=
6 > [convert]
6 > [convert]
7 > hg.saverev=False
7 > hg.saverev=False
8 > EOF
8 > EOF
9 $ hg help convert
9 $ hg help convert
10 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
10 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
11
11
12 convert a foreign SCM repository to a Mercurial one.
12 convert a foreign SCM repository to a Mercurial one.
13
13
14 Accepted source formats [identifiers]:
14 Accepted source formats [identifiers]:
15
15
16 - Mercurial [hg]
16 - Mercurial [hg]
17 - CVS [cvs]
17 - CVS [cvs]
18 - Darcs [darcs]
18 - Darcs [darcs]
19 - git [git]
19 - git [git]
20 - Subversion [svn]
20 - Subversion [svn]
21 - Monotone [mtn]
21 - Monotone [mtn]
22 - GNU Arch [gnuarch]
22 - GNU Arch [gnuarch]
23 - Bazaar [bzr]
23 - Bazaar [bzr]
24 - Perforce [p4]
24 - Perforce [p4]
25
25
26 Accepted destination formats [identifiers]:
26 Accepted destination formats [identifiers]:
27
27
28 - Mercurial [hg]
28 - Mercurial [hg]
29 - Subversion [svn] (history on branches is not preserved)
29 - Subversion [svn] (history on branches is not preserved)
30
30
31 If no revision is given, all revisions will be converted. Otherwise,
31 If no revision is given, all revisions will be converted. Otherwise,
32 convert will only import up to the named revision (given in a format
32 convert will only import up to the named revision (given in a format
33 understood by the source).
33 understood by the source).
34
34
35 If no destination directory name is specified, it defaults to the basename
35 If no destination directory name is specified, it defaults to the basename
36 of the source with "-hg" appended. If the destination repository doesn't
36 of the source with "-hg" appended. If the destination repository doesn't
37 exist, it will be created.
37 exist, it will be created.
38
38
39 By default, all sources except Mercurial will use --branchsort. Mercurial
39 By default, all sources except Mercurial will use --branchsort. Mercurial
40 uses --sourcesort to preserve original revision numbers order. Sort modes
40 uses --sourcesort to preserve original revision numbers order. Sort modes
41 have the following effects:
41 have the following effects:
42
42
43 --branchsort convert from parent to child revision when possible, which
43 --branchsort convert from parent to child revision when possible, which
44 means branches are usually converted one after the other.
44 means branches are usually converted one after the other.
45 It generates more compact repositories.
45 It generates more compact repositories.
46 --datesort sort revisions by date. Converted repositories have good-
46 --datesort sort revisions by date. Converted repositories have good-
47 looking changelogs but are often an order of magnitude
47 looking changelogs but are often an order of magnitude
48 larger than the same ones generated by --branchsort.
48 larger than the same ones generated by --branchsort.
49 --sourcesort try to preserve source revisions order, only supported by
49 --sourcesort try to preserve source revisions order, only supported by
50 Mercurial sources.
50 Mercurial sources.
51
51
52 If "REVMAP" isn't given, it will be put in a default location
52 If "REVMAP" isn't given, it will be put in a default location
53 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
53 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
54 maps each source commit ID to the destination ID for that revision, like
54 maps each source commit ID to the destination ID for that revision, like
55 so:
55 so:
56
56
57 <source ID> <destination ID>
57 <source ID> <destination ID>
58
58
59 If the file doesn't exist, it's automatically created. It's updated on
59 If the file doesn't exist, it's automatically created. It's updated on
60 each commit copied, so "hg convert" can be interrupted and can be run
60 each commit copied, so "hg convert" can be interrupted and can be run
61 repeatedly to copy new commits.
61 repeatedly to copy new commits.
62
62
63 The authormap is a simple text file that maps each source commit author to
63 The authormap is a simple text file that maps each source commit author to
64 a destination commit author. It is handy for source SCMs that use unix
64 a destination commit author. It is handy for source SCMs that use unix
65 logins to identify authors (eg: CVS). One line per author mapping and the
65 logins to identify authors (eg: CVS). One line per author mapping and the
66 line format is:
66 line format is:
67
67
68 source author = destination author
68 source author = destination author
69
69
70 Empty lines and lines starting with a "#" are ignored.
70 Empty lines and lines starting with a "#" are ignored.
71
71
72 The filemap is a file that allows filtering and remapping of files and
72 The filemap is a file that allows filtering and remapping of files and
73 directories. Each line can contain one of the following directives:
73 directories. Each line can contain one of the following directives:
74
74
75 include path/to/file-or-dir
75 include path/to/file-or-dir
76
76
77 exclude path/to/file-or-dir
77 exclude path/to/file-or-dir
78
78
79 rename path/to/source path/to/destination
79 rename path/to/source path/to/destination
80
80
81 Comment lines start with "#". A specified path matches if it equals the
81 Comment lines start with "#". A specified path matches if it equals the
82 full relative name of a file or one of its parent directories. The
82 full relative name of a file or one of its parent directories. The
83 "include" or "exclude" directive with the longest matching path applies,
83 "include" or "exclude" directive with the longest matching path applies,
84 so line order does not matter.
84 so line order does not matter.
85
85
86 The "include" directive causes a file, or all files under a directory, to
86 The "include" directive causes a file, or all files under a directory, to
87 be included in the destination repository, and the exclusion of all other
87 be included in the destination repository, and the exclusion of all other
88 files and directories not explicitly included. The "exclude" directive
88 files and directories not explicitly included. The "exclude" directive
89 causes files or directories to be omitted. The "rename" directive renames
89 causes files or directories to be omitted. The "rename" directive renames
90 a file or directory if it is converted. To rename from a subdirectory into
90 a file or directory if it is converted. To rename from a subdirectory into
91 the root of the repository, use "." as the path to rename to.
91 the root of the repository, use "." as the path to rename to.
92
92
93 The splicemap is a file that allows insertion of synthetic history,
93 The splicemap is a file that allows insertion of synthetic history,
94 letting you specify the parents of a revision. This is useful if you want
94 letting you specify the parents of a revision. This is useful if you want
95 to e.g. give a Subversion merge two parents, or graft two disconnected
95 to e.g. give a Subversion merge two parents, or graft two disconnected
96 series of history together. Each entry contains a key, followed by a
96 series of history together. Each entry contains a key, followed by a
97 space, followed by one or two comma-separated values:
97 space, followed by one or two comma-separated values:
98
98
99 key parent1, parent2
99 key parent1, parent2
100
100
101 The key is the revision ID in the source revision control system whose
101 The key is the revision ID in the source revision control system whose
102 parents should be modified (same format as a key in .hg/shamap). The
102 parents should be modified (same format as a key in .hg/shamap). The
103 values are the revision IDs (in either the source or destination revision
103 values are the revision IDs (in either the source or destination revision
104 control system) that should be used as the new parents for that node. For
104 control system) that should be used as the new parents for that node. For
105 example, if you have merged "release-1.0" into "trunk", then you should
105 example, if you have merged "release-1.0" into "trunk", then you should
106 specify the revision on "trunk" as the first parent and the one on the
106 specify the revision on "trunk" as the first parent and the one on the
107 "release-1.0" branch as the second.
107 "release-1.0" branch as the second.
108
108
109 The branchmap is a file that allows you to rename a branch when it is
109 The branchmap is a file that allows you to rename a branch when it is
110 being brought in from whatever external repository. When used in
110 being brought in from whatever external repository. When used in
111 conjunction with a splicemap, it allows for a powerful combination to help
111 conjunction with a splicemap, it allows for a powerful combination to help
112 fix even the most badly mismanaged repositories and turn them into nicely
112 fix even the most badly mismanaged repositories and turn them into nicely
113 structured Mercurial repositories. The branchmap contains lines of the
113 structured Mercurial repositories. The branchmap contains lines of the
114 form:
114 form:
115
115
116 original_branch_name new_branch_name
116 original_branch_name new_branch_name
117
117
118 where "original_branch_name" is the name of the branch in the source
118 where "original_branch_name" is the name of the branch in the source
119 repository, and "new_branch_name" is the name of the branch is the
119 repository, and "new_branch_name" is the name of the branch is the
120 destination repository. No whitespace is allowed in the branch names. This
120 destination repository. No whitespace is allowed in the branch names. This
121 can be used to (for instance) move code in one repository from "default"
121 can be used to (for instance) move code in one repository from "default"
122 to a named branch.
122 to a named branch.
123
123
124 Mercurial Source
124 Mercurial Source
125 ''''''''''''''''
125 ''''''''''''''''
126
126
127 The Mercurial source recognizes the following configuration options, which
127 The Mercurial source recognizes the following configuration options, which
128 you can set on the command line with "--config":
128 you can set on the command line with "--config":
129
129
130 convert.hg.ignoreerrors
130 convert.hg.ignoreerrors
131 ignore integrity errors when reading. Use it to fix Mercurial
131 ignore integrity errors when reading. Use it to fix
132 repositories with missing revlogs, by converting from and to
132 Mercurial repositories with missing revlogs, by converting
133 Mercurial. Default is False.
133 from and to Mercurial. Default is False.
134 convert.hg.saverev
134 convert.hg.saverev
135 store original revision ID in changeset (forces target IDs to
135 store original revision ID in changeset (forces target IDs
136 change). It takes a boolean argument and defaults to False.
136 to change). It takes a boolean argument and defaults to
137 False.
137 convert.hg.startrev
138 convert.hg.startrev
138 convert start revision and its descendants. It takes a hg
139 convert start revision and its descendants. It takes a hg
139 revision identifier and defaults to 0.
140 revision identifier and defaults to 0.
140
141
141 CVS Source
142 CVS Source
142 ''''''''''
143 ''''''''''
143
144
144 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
145 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
145 indicate the starting point of what will be converted. Direct access to
146 indicate the starting point of what will be converted. Direct access to
146 the repository files is not needed, unless of course the repository is
147 the repository files is not needed, unless of course the repository is
147 ":local:". The conversion uses the top level directory in the sandbox to
148 ":local:". The conversion uses the top level directory in the sandbox to
148 find the CVS repository, and then uses CVS rlog commands to find files to
149 find the CVS repository, and then uses CVS rlog commands to find files to
149 convert. This means that unless a filemap is given, all files under the
150 convert. This means that unless a filemap is given, all files under the
150 starting directory will be converted, and that any directory
151 starting directory will be converted, and that any directory
151 reorganization in the CVS sandbox is ignored.
152 reorganization in the CVS sandbox is ignored.
152
153
153 The following options can be used with "--config":
154 The following options can be used with "--config":
154
155
155 convert.cvsps.cache
156 convert.cvsps.cache
156 Set to False to disable remote log caching, for testing and
157 Set to False to disable remote log caching, for testing and
157 debugging purposes. Default is True.
158 debugging purposes. Default is True.
158 convert.cvsps.fuzz
159 convert.cvsps.fuzz
159 Specify the maximum time (in seconds) that is allowed between
160 Specify the maximum time (in seconds) that is allowed
160 commits with identical user and log message in a single
161 between commits with identical user and log message in a
161 changeset. When very large files were checked in as part of a
162 single changeset. When very large files were checked in as
162 changeset then the default may not be long enough. The default
163 part of a changeset then the default may not be long enough.
163 is 60.
164 The default is 60.
164 convert.cvsps.mergeto
165 convert.cvsps.mergeto
165 Specify a regular expression to which commit log messages are
166 Specify a regular expression to which commit log messages
166 matched. If a match occurs, then the conversion process will
167 are matched. If a match occurs, then the conversion process
167 insert a dummy revision merging the branch on which this log
168 will insert a dummy revision merging the branch on which
168 message occurs to the branch indicated in the regex. Default
169 this log message occurs to the branch indicated in the
169 is "{{mergetobranch ([-\w]+)}}"
170 regex. Default is "{{mergetobranch ([-\w]+)}}"
170 convert.cvsps.mergefrom
171 convert.cvsps.mergefrom
171 Specify a regular expression to which commit log messages are
172 Specify a regular expression to which commit log messages
172 matched. If a match occurs, then the conversion process will
173 are matched. If a match occurs, then the conversion process
173 add the most recent revision on the branch indicated in the
174 will add the most recent revision on the branch indicated in
174 regex as the second parent of the changeset. Default is
175 the regex as the second parent of the changeset. Default is
175 "{{mergefrombranch ([-\w]+)}}"
176 "{{mergefrombranch ([-\w]+)}}"
176 hook.cvslog
177 hook.cvslog Specify a Python function to be called at the end of
177 Specify a Python function to be called at the end of gathering
178 gathering the CVS log. The function is passed a list with
178 the CVS log. The function is passed a list with the log
179 the log entries, and can modify the entries in-place, or add
179 entries, and can modify the entries in-place, or add or delete
180 or delete them.
180 them.
181 hook.cvschangesets
181 hook.cvschangesets
182 Specify a Python function to be called after the changesets
182 Specify a Python function to be called after the changesets
183 are calculated from the the CVS log. The function is passed a
183 are calculated from the the CVS log. The function is passed
184 list with the changeset entries, and can modify the changesets
184 a list with the changeset entries, and can modify the
185 in-place, or add or delete them.
185 changesets in-place, or add or delete them.
186
186
187 An additional "debugcvsps" Mercurial command allows the builtin changeset
187 An additional "debugcvsps" Mercurial command allows the builtin changeset
188 merging code to be run without doing a conversion. Its parameters and
188 merging code to be run without doing a conversion. Its parameters and
189 output are similar to that of cvsps 2.1. Please see the command help for
189 output are similar to that of cvsps 2.1. Please see the command help for
190 more details.
190 more details.
191
191
192 Subversion Source
192 Subversion Source
193 '''''''''''''''''
193 '''''''''''''''''
194
194
195 Subversion source detects classical trunk/branches/tags layouts. By
195 Subversion source detects classical trunk/branches/tags layouts. By
196 default, the supplied "svn://repo/path/" source URL is converted as a
196 default, the supplied "svn://repo/path/" source URL is converted as a
197 single branch. If "svn://repo/path/trunk" exists it replaces the default
197 single branch. If "svn://repo/path/trunk" exists it replaces the default
198 branch. If "svn://repo/path/branches" exists, its subdirectories are
198 branch. If "svn://repo/path/branches" exists, its subdirectories are
199 listed as possible branches. If "svn://repo/path/tags" exists, it is
199 listed as possible branches. If "svn://repo/path/tags" exists, it is
200 looked for tags referencing converted branches. Default "trunk",
200 looked for tags referencing converted branches. Default "trunk",
201 "branches" and "tags" values can be overridden with following options. Set
201 "branches" and "tags" values can be overridden with following options. Set
202 them to paths relative to the source URL, or leave them blank to disable
202 them to paths relative to the source URL, or leave them blank to disable
203 auto detection.
203 auto detection.
204
204
205 The following options can be set with "--config":
205 The following options can be set with "--config":
206
206
207 convert.svn.branches
207 convert.svn.branches
208 specify the directory containing branches. The default is
208 specify the directory containing branches. The default is
209 "branches".
209 "branches".
210 convert.svn.tags
210 convert.svn.tags
211 specify the directory containing tags. The default is "tags".
211 specify the directory containing tags. The default is
212 "tags".
212 convert.svn.trunk
213 convert.svn.trunk
213 specify the name of the trunk branch. The default is "trunk".
214 specify the name of the trunk branch. The default is
215 "trunk".
214
216
215 Source history can be retrieved starting at a specific revision, instead
217 Source history can be retrieved starting at a specific revision, instead
216 of being integrally converted. Only single branch conversions are
218 of being integrally converted. Only single branch conversions are
217 supported.
219 supported.
218
220
219 convert.svn.startrev
221 convert.svn.startrev
220 specify start Subversion revision number. The default is 0.
222 specify start Subversion revision number. The default is 0.
221
223
222 Perforce Source
224 Perforce Source
223 '''''''''''''''
225 '''''''''''''''
224
226
225 The Perforce (P4) importer can be given a p4 depot path or a client
227 The Perforce (P4) importer can be given a p4 depot path or a client
226 specification as source. It will convert all files in the source to a flat
228 specification as source. It will convert all files in the source to a flat
227 Mercurial repository, ignoring labels, branches and integrations. Note
229 Mercurial repository, ignoring labels, branches and integrations. Note
228 that when a depot path is given you then usually should specify a target
230 that when a depot path is given you then usually should specify a target
229 directory, because otherwise the target may be named "...-hg".
231 directory, because otherwise the target may be named "...-hg".
230
232
231 It is possible to limit the amount of source history to be converted by
233 It is possible to limit the amount of source history to be converted by
232 specifying an initial Perforce revision:
234 specifying an initial Perforce revision:
233
235
234 convert.p4.startrev
236 convert.p4.startrev
235 specify initial Perforce revision (a Perforce changelist
237 specify initial Perforce revision (a Perforce changelist
236 number).
238 number).
237
239
238 Mercurial Destination
240 Mercurial Destination
239 '''''''''''''''''''''
241 '''''''''''''''''''''
240
242
241 The following options are supported:
243 The following options are supported:
242
244
243 convert.hg.clonebranches
245 convert.hg.clonebranches
244 dispatch source branches in separate clones. The default is
246 dispatch source branches in separate clones. The default is
245 False.
247 False.
246 convert.hg.tagsbranch
248 convert.hg.tagsbranch
247 branch name for tag revisions, defaults to "default".
249 branch name for tag revisions, defaults to "default".
248 convert.hg.usebranchnames
250 convert.hg.usebranchnames
249 preserve branch names. The default is True.
251 preserve branch names. The default is True.
250
252
251 options:
253 options:
252
254
253 -s --source-type TYPE source repository type
255 -s --source-type TYPE source repository type
254 -d --dest-type TYPE destination repository type
256 -d --dest-type TYPE destination repository type
255 -r --rev REV import up to target revision REV
257 -r --rev REV import up to target revision REV
256 -A --authormap FILE remap usernames using this file
258 -A --authormap FILE remap usernames using this file
257 --filemap FILE remap file names using contents of file
259 --filemap FILE remap file names using contents of file
258 --splicemap FILE splice synthesized history into place
260 --splicemap FILE splice synthesized history into place
259 --branchmap FILE change branch names while converting
261 --branchmap FILE change branch names while converting
260 --branchsort try to sort changesets by branches
262 --branchsort try to sort changesets by branches
261 --datesort try to sort changesets by date
263 --datesort try to sort changesets by date
262 --sourcesort preserve source changesets order
264 --sourcesort preserve source changesets order
263
265
264 use "hg -v help convert" to show more info
266 use "hg -v help convert" to show more info
265 $ hg init a
267 $ hg init a
266 $ cd a
268 $ cd a
267 $ echo a > a
269 $ echo a > a
268 $ hg ci -d'0 0' -Ama
270 $ hg ci -d'0 0' -Ama
269 adding a
271 adding a
270 $ hg cp a b
272 $ hg cp a b
271 $ hg ci -d'1 0' -mb
273 $ hg ci -d'1 0' -mb
272 $ hg rm a
274 $ hg rm a
273 $ hg ci -d'2 0' -mc
275 $ hg ci -d'2 0' -mc
274 $ hg mv b a
276 $ hg mv b a
275 $ hg ci -d'3 0' -md
277 $ hg ci -d'3 0' -md
276 $ echo a >> a
278 $ echo a >> a
277 $ hg ci -d'4 0' -me
279 $ hg ci -d'4 0' -me
278 $ cd ..
280 $ cd ..
279 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
281 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
280 assuming destination a-hg
282 assuming destination a-hg
281 initializing destination a-hg repository
283 initializing destination a-hg repository
282 scanning source...
284 scanning source...
283 sorting...
285 sorting...
284 converting...
286 converting...
285 4 a
287 4 a
286 3 b
288 3 b
287 2 c
289 2 c
288 1 d
290 1 d
289 0 e
291 0 e
290 $ hg --cwd a-hg pull ../a
292 $ hg --cwd a-hg pull ../a
291 pulling from ../a
293 pulling from ../a
292 searching for changes
294 searching for changes
293 no changes found
295 no changes found
294 $ touch bogusfile
296 $ touch bogusfile
295
297
296 should fail
298 should fail
297
299
298 $ hg convert a bogusfile
300 $ hg convert a bogusfile
299 initializing destination bogusfile repository
301 initializing destination bogusfile repository
300 abort: cannot create new bundle repository
302 abort: cannot create new bundle repository
301 [255]
303 [255]
302 $ mkdir bogusdir
304 $ mkdir bogusdir
303 $ chmod 000 bogusdir
305 $ chmod 000 bogusdir
304
306
305 should fail
307 should fail
306
308
307 $ hg convert a bogusdir
309 $ hg convert a bogusdir
308 abort: Permission denied: bogusdir
310 abort: Permission denied: bogusdir
309 [255]
311 [255]
310
312
311 should succeed
313 should succeed
312
314
313 $ chmod 700 bogusdir
315 $ chmod 700 bogusdir
314 $ hg convert a bogusdir
316 $ hg convert a bogusdir
315 initializing destination bogusdir repository
317 initializing destination bogusdir repository
316 scanning source...
318 scanning source...
317 sorting...
319 sorting...
318 converting...
320 converting...
319 4 a
321 4 a
320 3 b
322 3 b
321 2 c
323 2 c
322 1 d
324 1 d
323 0 e
325 0 e
324
326
325 test pre and post conversion actions
327 test pre and post conversion actions
326
328
327 $ echo 'include b' > filemap
329 $ echo 'include b' > filemap
328 $ hg convert --debug --filemap filemap a partialb | \
330 $ hg convert --debug --filemap filemap a partialb | \
329 > grep 'run hg'
331 > grep 'run hg'
330 run hg source pre-conversion action
332 run hg source pre-conversion action
331 run hg sink pre-conversion action
333 run hg sink pre-conversion action
332 run hg sink post-conversion action
334 run hg sink post-conversion action
333 run hg source post-conversion action
335 run hg source post-conversion action
334
336
335 converting empty dir should fail "nicely
337 converting empty dir should fail "nicely
336
338
337 $ mkdir emptydir
339 $ mkdir emptydir
338
340
339 override $PATH to ensure p4 not visible; use $PYTHON in case we're
341 override $PATH to ensure p4 not visible; use $PYTHON in case we're
340 running from a devel copy, not a temp installation
342 running from a devel copy, not a temp installation
341
343
342 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
344 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
343 assuming destination emptydir-hg
345 assuming destination emptydir-hg
344 initializing destination emptydir-hg repository
346 initializing destination emptydir-hg repository
345 emptydir does not look like a CVS checkout
347 emptydir does not look like a CVS checkout
346 emptydir does not look like a Git repository
348 emptydir does not look like a Git repository
347 emptydir does not look like a Subversion repository
349 emptydir does not look like a Subversion repository
348 emptydir is not a local Mercurial repository
350 emptydir is not a local Mercurial repository
349 emptydir does not look like a darcs repository
351 emptydir does not look like a darcs repository
350 emptydir does not look like a monotone repository
352 emptydir does not look like a monotone repository
351 emptydir does not look like a GNU Arch repository
353 emptydir does not look like a GNU Arch repository
352 emptydir does not look like a Bazaar repository
354 emptydir does not look like a Bazaar repository
353 cannot find required "p4" tool
355 cannot find required "p4" tool
354 abort: emptydir: missing or unsupported repository
356 abort: emptydir: missing or unsupported repository
355 [255]
357 [255]
356
358
357 convert with imaginary source type
359 convert with imaginary source type
358
360
359 $ hg convert --source-type foo a a-foo
361 $ hg convert --source-type foo a a-foo
360 initializing destination a-foo repository
362 initializing destination a-foo repository
361 abort: foo: invalid source repository type
363 abort: foo: invalid source repository type
362 [255]
364 [255]
363
365
364 convert with imaginary sink type
366 convert with imaginary sink type
365
367
366 $ hg convert --dest-type foo a a-foo
368 $ hg convert --dest-type foo a a-foo
367 abort: foo: invalid destination repository type
369 abort: foo: invalid destination repository type
368 [255]
370 [255]
369
371
370 testing: convert must not produce duplicate entries in fncache
372 testing: convert must not produce duplicate entries in fncache
371
373
372 $ hg convert a b
374 $ hg convert a b
373 initializing destination b repository
375 initializing destination b repository
374 scanning source...
376 scanning source...
375 sorting...
377 sorting...
376 converting...
378 converting...
377 4 a
379 4 a
378 3 b
380 3 b
379 2 c
381 2 c
380 1 d
382 1 d
381 0 e
383 0 e
382
384
383 contents of fncache file:
385 contents of fncache file:
384
386
385 $ cat b/.hg/store/fncache | sort
387 $ cat b/.hg/store/fncache | sort
386 data/a.i
388 data/a.i
387 data/b.i
389 data/b.i
388
390
389 test bogus URL
391 test bogus URL
390
392
391 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
393 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
392 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
394 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
393 [255]
395 [255]
@@ -1,764 +1,766 b''
1 == paragraphs ==
1 == paragraphs ==
2 60 column format:
2 60 column format:
3 ----------------------------------------------------------------------
3 ----------------------------------------------------------------------
4 This is some text in the first paragraph.
4 This is some text in the first paragraph.
5
5
6 A small indented paragraph. It is followed by some lines
6 A small indented paragraph. It is followed by some lines
7 containing random whitespace.
7 containing random whitespace.
8
8
9 The third and final paragraph.
9 The third and final paragraph.
10 ----------------------------------------------------------------------
10 ----------------------------------------------------------------------
11
11
12 30 column format:
12 30 column format:
13 ----------------------------------------------------------------------
13 ----------------------------------------------------------------------
14 This is some text in the first
14 This is some text in the first
15 paragraph.
15 paragraph.
16
16
17 A small indented paragraph.
17 A small indented paragraph.
18 It is followed by some lines
18 It is followed by some lines
19 containing random
19 containing random
20 whitespace.
20 whitespace.
21
21
22 The third and final paragraph.
22 The third and final paragraph.
23 ----------------------------------------------------------------------
23 ----------------------------------------------------------------------
24
24
25 html format:
25 html format:
26 ----------------------------------------------------------------------
26 ----------------------------------------------------------------------
27 <p>
27 <p>
28 This is some text in the first paragraph.
28 This is some text in the first paragraph.
29 </p>
29 </p>
30 <p>
30 <p>
31 A small indented paragraph.
31 A small indented paragraph.
32 It is followed by some lines
32 It is followed by some lines
33 containing random whitespace.
33 containing random whitespace.
34 </p>
34 </p>
35 <p>
35 <p>
36 The third and final paragraph.
36 The third and final paragraph.
37 </p>
37 </p>
38 ----------------------------------------------------------------------
38 ----------------------------------------------------------------------
39
39
40 == definitions ==
40 == definitions ==
41 60 column format:
41 60 column format:
42 ----------------------------------------------------------------------
42 ----------------------------------------------------------------------
43 A Term
43 A Term
44 Definition. The indented lines make up the definition.
44 Definition. The indented lines make up the definition.
45
45
46 Another Term
46 Another Term
47 Another definition. The final line in the definition
47 Another definition. The final line in the definition
48 determines the indentation, so this will be indented
48 determines the indentation, so this will be indented
49 with four spaces.
49 with four spaces.
50
50
51 A Nested/Indented Term
51 A Nested/Indented Term
52 Definition.
52 Definition.
53 ----------------------------------------------------------------------
53 ----------------------------------------------------------------------
54
54
55 30 column format:
55 30 column format:
56 ----------------------------------------------------------------------
56 ----------------------------------------------------------------------
57 A Term
57 A Term
58 Definition. The indented
58 Definition. The indented
59 lines make up the
59 lines make up the
60 definition.
60 definition.
61
61
62 Another Term
62 Another Term
63 Another definition. The
63 Another definition. The
64 final line in the
64 final line in the
65 definition determines the
65 definition determines the
66 indentation, so this will
66 indentation, so this will
67 be indented with four
67 be indented with four
68 spaces.
68 spaces.
69
69
70 A Nested/Indented Term
70 A Nested/Indented Term
71 Definition.
71 Definition.
72 ----------------------------------------------------------------------
72 ----------------------------------------------------------------------
73
73
74 html format:
74 html format:
75 ----------------------------------------------------------------------
75 ----------------------------------------------------------------------
76 <dl>
76 <dl>
77 <dt>A Term
77 <dt>A Term
78 <dd>Definition. The indented lines make up the definition.
78 <dd>Definition. The indented lines make up the definition.
79 <dt>Another Term
79 <dt>Another Term
80 <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
80 <dd>Another definition. The final line in the definition determines the indentation, so this will be indented with four spaces.
81 <dt>A Nested/Indented Term
81 <dt>A Nested/Indented Term
82 <dd>Definition.
82 <dd>Definition.
83 </dl>
83 </dl>
84 ----------------------------------------------------------------------
84 ----------------------------------------------------------------------
85
85
86 == literals ==
86 == literals ==
87 60 column format:
87 60 column format:
88 ----------------------------------------------------------------------
88 ----------------------------------------------------------------------
89 The fully minimized form is the most convenient form:
89 The fully minimized form is the most convenient form:
90
90
91 Hello
91 Hello
92 literal
92 literal
93 world
93 world
94
94
95 In the partially minimized form a paragraph simply ends with
95 In the partially minimized form a paragraph simply ends with
96 space-double-colon.
96 space-double-colon.
97
97
98 ////////////////////////////////////////
98 ////////////////////////////////////////
99 long un-wrapped line in a literal block
99 long un-wrapped line in a literal block
100 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
100 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
101
101
102 This literal block is started with '::',
102 This literal block is started with '::',
103 the so-called expanded form. The paragraph
103 the so-called expanded form. The paragraph
104 with '::' disappears in the final output.
104 with '::' disappears in the final output.
105 ----------------------------------------------------------------------
105 ----------------------------------------------------------------------
106
106
107 30 column format:
107 30 column format:
108 ----------------------------------------------------------------------
108 ----------------------------------------------------------------------
109 The fully minimized form is
109 The fully minimized form is
110 the most convenient form:
110 the most convenient form:
111
111
112 Hello
112 Hello
113 literal
113 literal
114 world
114 world
115
115
116 In the partially minimized
116 In the partially minimized
117 form a paragraph simply ends
117 form a paragraph simply ends
118 with space-double-colon.
118 with space-double-colon.
119
119
120 ////////////////////////////////////////
120 ////////////////////////////////////////
121 long un-wrapped line in a literal block
121 long un-wrapped line in a literal block
122 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
122 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
123
123
124 This literal block is started with '::',
124 This literal block is started with '::',
125 the so-called expanded form. The paragraph
125 the so-called expanded form. The paragraph
126 with '::' disappears in the final output.
126 with '::' disappears in the final output.
127 ----------------------------------------------------------------------
127 ----------------------------------------------------------------------
128
128
129 html format:
129 html format:
130 ----------------------------------------------------------------------
130 ----------------------------------------------------------------------
131 <p>
131 <p>
132 The fully minimized form is the most
132 The fully minimized form is the most
133 convenient form:
133 convenient form:
134 </p>
134 </p>
135 <pre>
135 <pre>
136 Hello
136 Hello
137 literal
137 literal
138 world
138 world
139 </pre>
139 </pre>
140 <p>
140 <p>
141 In the partially minimized form a paragraph
141 In the partially minimized form a paragraph
142 simply ends with space-double-colon.
142 simply ends with space-double-colon.
143 </p>
143 </p>
144 <pre>
144 <pre>
145 ////////////////////////////////////////
145 ////////////////////////////////////////
146 long un-wrapped line in a literal block
146 long un-wrapped line in a literal block
147 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
147 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
148 </pre>
148 </pre>
149 <pre>
149 <pre>
150 This literal block is started with '::',
150 This literal block is started with '::',
151 the so-called expanded form. The paragraph
151 the so-called expanded form. The paragraph
152 with '::' disappears in the final output.
152 with '::' disappears in the final output.
153 </pre>
153 </pre>
154 ----------------------------------------------------------------------
154 ----------------------------------------------------------------------
155
155
156 == lists ==
156 == lists ==
157 60 column format:
157 60 column format:
158 ----------------------------------------------------------------------
158 ----------------------------------------------------------------------
159 - This is the first list item.
159 - This is the first list item.
160
160
161 Second paragraph in the first list item.
161 Second paragraph in the first list item.
162
162
163 - List items need not be separated by a blank line.
163 - List items need not be separated by a blank line.
164 - And will be rendered without one in any case.
164 - And will be rendered without one in any case.
165
165
166 We can have indented lists:
166 We can have indented lists:
167
167
168 - This is an indented list item
168 - This is an indented list item
169 - Another indented list item:
169 - Another indented list item:
170
170
171 - A literal block in the middle
171 - A literal block in the middle
172 of an indented list.
172 of an indented list.
173
173
174 (The above is not a list item since we are in the literal block.)
174 (The above is not a list item since we are in the literal block.)
175
175
176 Literal block with no indentation (apart from
176 Literal block with no indentation (apart from
177 the two spaces added to all literal blocks).
177 the two spaces added to all literal blocks).
178
178
179 1. This is an enumerated list (first item).
179 1. This is an enumerated list (first item).
180 2. Continuing with the second item.
180 2. Continuing with the second item.
181 (1) foo
181 (1) foo
182 (2) bar
182 (2) bar
183 1) Another
183 1) Another
184 2) List
184 2) List
185
185
186 Line blocks are also a form of list:
186 Line blocks are also a form of list:
187
187
188 This is the first line. The line continues here.
188 This is the first line. The line continues here.
189 This is the second line.
189 This is the second line.
190 ----------------------------------------------------------------------
190 ----------------------------------------------------------------------
191
191
192 30 column format:
192 30 column format:
193 ----------------------------------------------------------------------
193 ----------------------------------------------------------------------
194 - This is the first list item.
194 - This is the first list item.
195
195
196 Second paragraph in the
196 Second paragraph in the
197 first list item.
197 first list item.
198
198
199 - List items need not be
199 - List items need not be
200 separated by a blank line.
200 separated by a blank line.
201 - And will be rendered without
201 - And will be rendered without
202 one in any case.
202 one in any case.
203
203
204 We can have indented lists:
204 We can have indented lists:
205
205
206 - This is an indented list
206 - This is an indented list
207 item
207 item
208 - Another indented list
208 - Another indented list
209 item:
209 item:
210
210
211 - A literal block in the middle
211 - A literal block in the middle
212 of an indented list.
212 of an indented list.
213
213
214 (The above is not a list item since we are in the literal block.)
214 (The above is not a list item since we are in the literal block.)
215
215
216 Literal block with no indentation (apart from
216 Literal block with no indentation (apart from
217 the two spaces added to all literal blocks).
217 the two spaces added to all literal blocks).
218
218
219 1. This is an enumerated list
219 1. This is an enumerated list
220 (first item).
220 (first item).
221 2. Continuing with the second
221 2. Continuing with the second
222 item.
222 item.
223 (1) foo
223 (1) foo
224 (2) bar
224 (2) bar
225 1) Another
225 1) Another
226 2) List
226 2) List
227
227
228 Line blocks are also a form of
228 Line blocks are also a form of
229 list:
229 list:
230
230
231 This is the first line. The
231 This is the first line. The
232 line continues here.
232 line continues here.
233 This is the second line.
233 This is the second line.
234 ----------------------------------------------------------------------
234 ----------------------------------------------------------------------
235
235
236 html format:
236 html format:
237 ----------------------------------------------------------------------
237 ----------------------------------------------------------------------
238 <ul>
238 <ul>
239 <li> This is the first list item.
239 <li> This is the first list item.
240 <p>
240 <p>
241 Second paragraph in the first list item.
241 Second paragraph in the first list item.
242 </p>
242 </p>
243 <li> List items need not be separated by a blank line.
243 <li> List items need not be separated by a blank line.
244 <li> And will be rendered without one in any case.
244 <li> And will be rendered without one in any case.
245 </ul>
245 </ul>
246 <p>
246 <p>
247 We can have indented lists:
247 We can have indented lists:
248 </p>
248 </p>
249 <ul>
249 <ul>
250 <li> This is an indented list item
250 <li> This is an indented list item
251 <li> Another indented list item:
251 <li> Another indented list item:
252 <pre>
252 <pre>
253 - A literal block in the middle
253 - A literal block in the middle
254 of an indented list.
254 of an indented list.
255 </pre>
255 </pre>
256 <pre>
256 <pre>
257 (The above is not a list item since we are in the literal block.)
257 (The above is not a list item since we are in the literal block.)
258 </pre>
258 </pre>
259 </ul>
259 </ul>
260 <pre>
260 <pre>
261 Literal block with no indentation (apart from
261 Literal block with no indentation (apart from
262 the two spaces added to all literal blocks).
262 the two spaces added to all literal blocks).
263 </pre>
263 </pre>
264 <ol>
264 <ol>
265 <li> This is an enumerated list (first item).
265 <li> This is an enumerated list (first item).
266 <li> Continuing with the second item.
266 <li> Continuing with the second item.
267 <li> foo
267 <li> foo
268 <li> bar
268 <li> bar
269 <li> Another
269 <li> Another
270 <li> List
270 <li> List
271 </ol>
271 </ol>
272 <p>
272 <p>
273 Line blocks are also a form of list:
273 Line blocks are also a form of list:
274 </p>
274 </p>
275 <ol>
275 <ol>
276 <li> This is the first line. The line continues here.
276 <li> This is the first line. The line continues here.
277 <li> This is the second line.
277 <li> This is the second line.
278 </ol>
278 </ol>
279 ----------------------------------------------------------------------
279 ----------------------------------------------------------------------
280
280
281 == options ==
281 == options ==
282 60 column format:
282 60 column format:
283 ----------------------------------------------------------------------
283 ----------------------------------------------------------------------
284 There is support for simple option lists, but only with long
284 There is support for simple option lists, but only with long
285 options:
285 options:
286
286
287 -X --exclude filter an option with a short and long option
287 -X --exclude filter an option with a short and long option
288 with an argument
288 with an argument
289 -I --include an option with both a short option and
289 -I --include an option with both a short option and
290 a long option
290 a long option
291 --all Output all.
291 --all Output all.
292 --both Output both (this description is quite
292 --both Output both (this description is quite
293 long).
293 long).
294 --long Output all day long.
294 --long Output all day long.
295 --par This option has two paragraphs in its
295 --par This option has two paragraphs in its
296 description. This is the first.
296 description. This is the first.
297
297
298 This is the second. Blank lines may
298 This is the second. Blank lines may
299 be omitted between options (as above)
299 be omitted between options (as above)
300 or left in (as here).
300 or left in (as here).
301
301
302 The next paragraph looks like an option list, but lacks the
302 The next paragraph looks like an option list, but lacks the
303 two-space marker after the option. It is treated as a normal
303 two-space marker after the option. It is treated as a normal
304 paragraph:
304 paragraph:
305
305
306 --foo bar baz
306 --foo bar baz
307 ----------------------------------------------------------------------
307 ----------------------------------------------------------------------
308
308
309 30 column format:
309 30 column format:
310 ----------------------------------------------------------------------
310 ----------------------------------------------------------------------
311 There is support for simple
311 There is support for simple
312 option lists, but only with
312 option lists, but only with
313 long options:
313 long options:
314
314
315 -X --exclude filter an
315 -X --exclude filter an
316 option
316 option
317 with a
317 with a
318 short
318 short
319 and
319 and
320 long
320 long
321 option
321 option
322 with an
322 with an
323 argumen
323 argumen
324 t
324 t
325 -I --include an
325 -I --include an
326 option
326 option
327 with
327 with
328 both a
328 both a
329 short
329 short
330 option
330 option
331 and a
331 and a
332 long
332 long
333 option
333 option
334 --all Output
334 --all Output
335 all.
335 all.
336 --both Output
336 --both Output
337 both
337 both
338 (this d
338 (this d
339 escript
339 escript
340 ion is
340 ion is
341 quite
341 quite
342 long).
342 long).
343 --long Output
343 --long Output
344 all day
344 all day
345 long.
345 long.
346 --par This
346 --par This
347 option
347 option
348 has two
348 has two
349 paragra
349 paragra
350 phs in
350 phs in
351 its des
351 its des
352 criptio
352 criptio
353 n. This
353 n. This
354 is the
354 is the
355 first.
355 first.
356
356
357 This is
357 This is
358 the
358 the
359 second.
359 second.
360 Blank
360 Blank
361 lines
361 lines
362 may be
362 may be
363 omitted
363 omitted
364 between
364 between
365 options
365 options
366 (as
366 (as
367 above)
367 above)
368 or left
368 or left
369 in (as
369 in (as
370 here).
370 here).
371
371
372 The next paragraph looks like
372 The next paragraph looks like
373 an option list, but lacks the
373 an option list, but lacks the
374 two-space marker after the
374 two-space marker after the
375 option. It is treated as a
375 option. It is treated as a
376 normal paragraph:
376 normal paragraph:
377
377
378 --foo bar baz
378 --foo bar baz
379 ----------------------------------------------------------------------
379 ----------------------------------------------------------------------
380
380
381 html format:
381 html format:
382 ----------------------------------------------------------------------
382 ----------------------------------------------------------------------
383 <p>
383 <p>
384 There is support for simple option lists,
384 There is support for simple option lists,
385 but only with long options:
385 but only with long options:
386 </p>
386 </p>
387 <dl>
387 <dl>
388 <dt>-X --exclude filter
388 <dt>-X --exclude filter
389 <dd>an option with a short and long option with an argument
389 <dd>an option with a short and long option with an argument
390 <dt>-I --include
390 <dt>-I --include
391 <dd>an option with both a short option and a long option
391 <dd>an option with both a short option and a long option
392 <dt> --all
392 <dt> --all
393 <dd>Output all.
393 <dd>Output all.
394 <dt> --both
394 <dt> --both
395 <dd>Output both (this description is quite long).
395 <dd>Output both (this description is quite long).
396 <dt> --long
396 <dt> --long
397 <dd>Output all day long.
397 <dd>Output all day long.
398 <dt> --par
398 <dt> --par
399 <dd>This option has two paragraphs in its description. This is the first.
399 <dd>This option has two paragraphs in its description. This is the first.
400 <p>
400 <p>
401 This is the second. Blank lines may be omitted between
401 This is the second. Blank lines may be omitted between
402 options (as above) or left in (as here).
402 options (as above) or left in (as here).
403 </p>
403 </p>
404 </dl>
404 </dl>
405 <p>
405 <p>
406 The next paragraph looks like an option list, but lacks the two-space
406 The next paragraph looks like an option list, but lacks the two-space
407 marker after the option. It is treated as a normal paragraph:
407 marker after the option. It is treated as a normal paragraph:
408 </p>
408 </p>
409 <p>
409 <p>
410 --foo bar baz
410 --foo bar baz
411 </p>
411 </p>
412 ----------------------------------------------------------------------
412 ----------------------------------------------------------------------
413
413
414 == fields ==
414 == fields ==
415 60 column format:
415 60 column format:
416 ----------------------------------------------------------------------
416 ----------------------------------------------------------------------
417 a First item.
417 a First item.
418 ab Second item. Indentation and wrapping is handled
418 ab Second item. Indentation and wrapping is
419 automatically.
419 handled automatically.
420
420
421 Next list:
421 Next list:
422
422
423 small The larger key below triggers full indentation
423 small The larger key below triggers full indentation
424 here.
424 here.
425 much too large
425 much too large
426 This key is big enough to get its own line.
426 This key is big enough to get its own line.
427 ----------------------------------------------------------------------
427 ----------------------------------------------------------------------
428
428
429 30 column format:
429 30 column format:
430 ----------------------------------------------------------------------
430 ----------------------------------------------------------------------
431 a First item.
431 a First item.
432 ab Second item. Indentation
432 ab Second item.
433 and wrapping is handled
433 Indentation and
434 wrapping is
435 handled
434 automatically.
436 automatically.
435
437
436 Next list:
438 Next list:
437
439
438 small The larger key
440 small The larger key
439 below triggers
441 below triggers
440 full indentation
442 full indentation
441 here.
443 here.
442 much too large
444 much too large
443 This key is big
445 This key is big
444 enough to get its
446 enough to get
445 own line.
447 its own line.
446 ----------------------------------------------------------------------
448 ----------------------------------------------------------------------
447
449
448 html format:
450 html format:
449 ----------------------------------------------------------------------
451 ----------------------------------------------------------------------
450 <dl>
452 <dl>
451 <dt>a
453 <dt>a
452 <dd>First item.
454 <dd>First item.
453 <dt>ab
455 <dt>ab
454 <dd>Second item. Indentation and wrapping is handled automatically.
456 <dd>Second item. Indentation and wrapping is handled automatically.
455 </dl>
457 </dl>
456 <p>
458 <p>
457 Next list:
459 Next list:
458 </p>
460 </p>
459 <dl>
461 <dl>
460 <dt>small
462 <dt>small
461 <dd>The larger key below triggers full indentation here.
463 <dd>The larger key below triggers full indentation here.
462 <dt>much too large
464 <dt>much too large
463 <dd>This key is big enough to get its own line.
465 <dd>This key is big enough to get its own line.
464 </dl>
466 </dl>
465 ----------------------------------------------------------------------
467 ----------------------------------------------------------------------
466
468
467 == containers (normal) ==
469 == containers (normal) ==
468 60 column format:
470 60 column format:
469 ----------------------------------------------------------------------
471 ----------------------------------------------------------------------
470 Normal output.
472 Normal output.
471 ----------------------------------------------------------------------
473 ----------------------------------------------------------------------
472
474
473 30 column format:
475 30 column format:
474 ----------------------------------------------------------------------
476 ----------------------------------------------------------------------
475 Normal output.
477 Normal output.
476 ----------------------------------------------------------------------
478 ----------------------------------------------------------------------
477
479
478 html format:
480 html format:
479 ----------------------------------------------------------------------
481 ----------------------------------------------------------------------
480 <p>
482 <p>
481 Normal output.
483 Normal output.
482 </p>
484 </p>
483 ----------------------------------------------------------------------
485 ----------------------------------------------------------------------
484
486
485 == containers (verbose) ==
487 == containers (verbose) ==
486 60 column format:
488 60 column format:
487 ----------------------------------------------------------------------
489 ----------------------------------------------------------------------
488 Normal output.
490 Normal output.
489
491
490 Verbose output.
492 Verbose output.
491 ----------------------------------------------------------------------
493 ----------------------------------------------------------------------
492 ['debug', 'debug']
494 ['debug', 'debug']
493 ----------------------------------------------------------------------
495 ----------------------------------------------------------------------
494
496
495 30 column format:
497 30 column format:
496 ----------------------------------------------------------------------
498 ----------------------------------------------------------------------
497 Normal output.
499 Normal output.
498
500
499 Verbose output.
501 Verbose output.
500 ----------------------------------------------------------------------
502 ----------------------------------------------------------------------
501 ['debug', 'debug']
503 ['debug', 'debug']
502 ----------------------------------------------------------------------
504 ----------------------------------------------------------------------
503
505
504 html format:
506 html format:
505 ----------------------------------------------------------------------
507 ----------------------------------------------------------------------
506 <p>
508 <p>
507 Normal output.
509 Normal output.
508 </p>
510 </p>
509 <p>
511 <p>
510 Verbose output.
512 Verbose output.
511 </p>
513 </p>
512 ----------------------------------------------------------------------
514 ----------------------------------------------------------------------
513 ['debug', 'debug']
515 ['debug', 'debug']
514 ----------------------------------------------------------------------
516 ----------------------------------------------------------------------
515
517
516 == containers (debug) ==
518 == containers (debug) ==
517 60 column format:
519 60 column format:
518 ----------------------------------------------------------------------
520 ----------------------------------------------------------------------
519 Normal output.
521 Normal output.
520
522
521 Initial debug output.
523 Initial debug output.
522 ----------------------------------------------------------------------
524 ----------------------------------------------------------------------
523 ['verbose']
525 ['verbose']
524 ----------------------------------------------------------------------
526 ----------------------------------------------------------------------
525
527
526 30 column format:
528 30 column format:
527 ----------------------------------------------------------------------
529 ----------------------------------------------------------------------
528 Normal output.
530 Normal output.
529
531
530 Initial debug output.
532 Initial debug output.
531 ----------------------------------------------------------------------
533 ----------------------------------------------------------------------
532 ['verbose']
534 ['verbose']
533 ----------------------------------------------------------------------
535 ----------------------------------------------------------------------
534
536
535 html format:
537 html format:
536 ----------------------------------------------------------------------
538 ----------------------------------------------------------------------
537 <p>
539 <p>
538 Normal output.
540 Normal output.
539 </p>
541 </p>
540 <p>
542 <p>
541 Initial debug output.
543 Initial debug output.
542 </p>
544 </p>
543 ----------------------------------------------------------------------
545 ----------------------------------------------------------------------
544 ['verbose']
546 ['verbose']
545 ----------------------------------------------------------------------
547 ----------------------------------------------------------------------
546
548
547 == containers (verbose debug) ==
549 == containers (verbose debug) ==
548 60 column format:
550 60 column format:
549 ----------------------------------------------------------------------
551 ----------------------------------------------------------------------
550 Normal output.
552 Normal output.
551
553
552 Initial debug output.
554 Initial debug output.
553
555
554 Verbose output.
556 Verbose output.
555
557
556 Debug output.
558 Debug output.
557 ----------------------------------------------------------------------
559 ----------------------------------------------------------------------
558 []
560 []
559 ----------------------------------------------------------------------
561 ----------------------------------------------------------------------
560
562
561 30 column format:
563 30 column format:
562 ----------------------------------------------------------------------
564 ----------------------------------------------------------------------
563 Normal output.
565 Normal output.
564
566
565 Initial debug output.
567 Initial debug output.
566
568
567 Verbose output.
569 Verbose output.
568
570
569 Debug output.
571 Debug output.
570 ----------------------------------------------------------------------
572 ----------------------------------------------------------------------
571 []
573 []
572 ----------------------------------------------------------------------
574 ----------------------------------------------------------------------
573
575
574 html format:
576 html format:
575 ----------------------------------------------------------------------
577 ----------------------------------------------------------------------
576 <p>
578 <p>
577 Normal output.
579 Normal output.
578 </p>
580 </p>
579 <p>
581 <p>
580 Initial debug output.
582 Initial debug output.
581 </p>
583 </p>
582 <p>
584 <p>
583 Verbose output.
585 Verbose output.
584 </p>
586 </p>
585 <p>
587 <p>
586 Debug output.
588 Debug output.
587 </p>
589 </p>
588 ----------------------------------------------------------------------
590 ----------------------------------------------------------------------
589 []
591 []
590 ----------------------------------------------------------------------
592 ----------------------------------------------------------------------
591
593
592 == roles ==
594 == roles ==
593 60 column format:
595 60 column format:
594 ----------------------------------------------------------------------
596 ----------------------------------------------------------------------
595 Please see "hg add".
597 Please see "hg add".
596 ----------------------------------------------------------------------
598 ----------------------------------------------------------------------
597
599
598 30 column format:
600 30 column format:
599 ----------------------------------------------------------------------
601 ----------------------------------------------------------------------
600 Please see "hg add".
602 Please see "hg add".
601 ----------------------------------------------------------------------
603 ----------------------------------------------------------------------
602
604
603 html format:
605 html format:
604 ----------------------------------------------------------------------
606 ----------------------------------------------------------------------
605 <p>
607 <p>
606 Please see "hg add".
608 Please see "hg add".
607 </p>
609 </p>
608 ----------------------------------------------------------------------
610 ----------------------------------------------------------------------
609
611
610 == sections ==
612 == sections ==
611 60 column format:
613 60 column format:
612 ----------------------------------------------------------------------
614 ----------------------------------------------------------------------
613 Title
615 Title
614 =====
616 =====
615
617
616 Section
618 Section
617 -------
619 -------
618
620
619 Subsection
621 Subsection
620 ''''''''''
622 ''''''''''
621
623
622 Markup: "foo" and "hg help"
624 Markup: "foo" and "hg help"
623 ---------------------------
625 ---------------------------
624 ----------------------------------------------------------------------
626 ----------------------------------------------------------------------
625
627
626 30 column format:
628 30 column format:
627 ----------------------------------------------------------------------
629 ----------------------------------------------------------------------
628 Title
630 Title
629 =====
631 =====
630
632
631 Section
633 Section
632 -------
634 -------
633
635
634 Subsection
636 Subsection
635 ''''''''''
637 ''''''''''
636
638
637 Markup: "foo" and "hg help"
639 Markup: "foo" and "hg help"
638 ---------------------------
640 ---------------------------
639 ----------------------------------------------------------------------
641 ----------------------------------------------------------------------
640
642
641 html format:
643 html format:
642 ----------------------------------------------------------------------
644 ----------------------------------------------------------------------
643 <h1>Title</h1>
645 <h1>Title</h1>
644 <h2>Section</h2>
646 <h2>Section</h2>
645 <h3>Subsection</h3>
647 <h3>Subsection</h3>
646 <h2>Markup: "foo" and "hg help"</h2>
648 <h2>Markup: "foo" and "hg help"</h2>
647 ----------------------------------------------------------------------
649 ----------------------------------------------------------------------
648
650
649 == admonitions ==
651 == admonitions ==
650 60 column format:
652 60 column format:
651 ----------------------------------------------------------------------
653 ----------------------------------------------------------------------
652 Note:
654 Note:
653 This is a note
655 This is a note
654
656
655 - Bullet 1
657 - Bullet 1
656 - Bullet 2
658 - Bullet 2
657
659
658 Warning!
660 Warning!
659 This is a warning Second input line of warning
661 This is a warning Second input line of warning
660
662
661 !Danger!
663 !Danger!
662 This is danger
664 This is danger
663 ----------------------------------------------------------------------
665 ----------------------------------------------------------------------
664
666
665 30 column format:
667 30 column format:
666 ----------------------------------------------------------------------
668 ----------------------------------------------------------------------
667 Note:
669 Note:
668 This is a note
670 This is a note
669
671
670 - Bullet 1
672 - Bullet 1
671 - Bullet 2
673 - Bullet 2
672
674
673 Warning!
675 Warning!
674 This is a warning Second
676 This is a warning Second
675 input line of warning
677 input line of warning
676
678
677 !Danger!
679 !Danger!
678 This is danger
680 This is danger
679 ----------------------------------------------------------------------
681 ----------------------------------------------------------------------
680
682
681 html format:
683 html format:
682 ----------------------------------------------------------------------
684 ----------------------------------------------------------------------
683 <p>
685 <p>
684 <b>Note:</b> This is a note
686 <b>Note:</b> This is a note
685 </p>
687 </p>
686 <ul>
688 <ul>
687 <li> Bullet 1
689 <li> Bullet 1
688 <li> Bullet 2
690 <li> Bullet 2
689 </ul>
691 </ul>
690 <p>
692 <p>
691 <b>Warning!</b> This is a warning Second input line of warning
693 <b>Warning!</b> This is a warning Second input line of warning
692 </p>
694 </p>
693 <p>
695 <p>
694 <b>!Danger!</b> This is danger
696 <b>!Danger!</b> This is danger
695 </p>
697 </p>
696 ----------------------------------------------------------------------
698 ----------------------------------------------------------------------
697
699
698 == comments ==
700 == comments ==
699 60 column format:
701 60 column format:
700 ----------------------------------------------------------------------
702 ----------------------------------------------------------------------
701 Some text.
703 Some text.
702
704
703 Some indented text.
705 Some indented text.
704
706
705 Empty comment above
707 Empty comment above
706 ----------------------------------------------------------------------
708 ----------------------------------------------------------------------
707
709
708 30 column format:
710 30 column format:
709 ----------------------------------------------------------------------
711 ----------------------------------------------------------------------
710 Some text.
712 Some text.
711
713
712 Some indented text.
714 Some indented text.
713
715
714 Empty comment above
716 Empty comment above
715 ----------------------------------------------------------------------
717 ----------------------------------------------------------------------
716
718
717 html format:
719 html format:
718 ----------------------------------------------------------------------
720 ----------------------------------------------------------------------
719 <p>
721 <p>
720 Some text.
722 Some text.
721 </p>
723 </p>
722 <p>
724 <p>
723 Some indented text.
725 Some indented text.
724 </p>
726 </p>
725 <p>
727 <p>
726 Empty comment above
728 Empty comment above
727 </p>
729 </p>
728 ----------------------------------------------------------------------
730 ----------------------------------------------------------------------
729
731
730 === === ========================================
732 === === ========================================
731 a b c
733 a b c
732 === === ========================================
734 === === ========================================
733 1 2 3
735 1 2 3
734 foo bar baz this list is very very very long man
736 foo bar baz this list is very very very long man
735 === === ========================================
737 === === ========================================
736
738
737 == table ==
739 == table ==
738 60 column format:
740 60 column format:
739 ----------------------------------------------------------------------
741 ----------------------------------------------------------------------
740 a b c
742 a b c
741 ------------------------------------------------
743 ------------------------------------------------
742 1 2 3
744 1 2 3
743 foo bar baz this list is very very very long man
745 foo bar baz this list is very very very long man
744 ----------------------------------------------------------------------
746 ----------------------------------------------------------------------
745
747
746 30 column format:
748 30 column format:
747 ----------------------------------------------------------------------
749 ----------------------------------------------------------------------
748 a b c
750 a b c
749 ------------------------------
751 ------------------------------
750 1 2 3
752 1 2 3
751 foo bar baz this list is
753 foo bar baz this list is
752 very very very long
754 very very very long
753 man
755 man
754 ----------------------------------------------------------------------
756 ----------------------------------------------------------------------
755
757
756 html format:
758 html format:
757 ----------------------------------------------------------------------
759 ----------------------------------------------------------------------
758 <table>
760 <table>
759 <tr><th>a</th><th>b</th><th>c</th></tr>
761 <tr><th>a</th><th>b</th><th>c</th></tr>
760 <tr><td>1</td><td>2</td><td>3</td></tr>
762 <tr><td>1</td><td>2</td><td>3</td></tr>
761 <tr><td>foo</td><td>bar</td><td>baz this list is very very very long man</td></tr>
763 <tr><td>foo</td><td>bar</td><td>baz this list is very very very long man</td></tr>
762 </table>
764 </table>
763 ----------------------------------------------------------------------
765 ----------------------------------------------------------------------
764
766
General Comments 0
You need to be logged in to leave comments. Login now