comparison mercurial/minirst.py @ 10443:62d484a81dfe

minirst: support containers Text can be grouped into generic containers in reStructuredText: .. container:: foo This is text inside a "foo" container. .. container:: bar This is nested inside two containers. The minirst parser now recognizes these containers. The containers are either pruned completely from the output (included all nested blocks) or they are simply un-indented. So if 'foo' and 'bar' containers are kept, the above example will result in: This is text inside a "foo" container. This is nested inside two containers. If only 'foo' containers are kept, we get: This is text inside a "foo" container. No output is made if only 'bar' containers are kept. This feature will come in handy for implementing different levels of help output (e.g., verbose and debug level help texts).
author Martin Geisler <mg@lazybytes.net>
date Sun, 04 Oct 2009 22:03:41 +0200
parents 08a0f04b56bd
children e99e0e077bc4
comparison
equal deleted inserted replaced
10442:662b0f9eb148 10443:62d484a81dfe
1 # minirst.py - minimal reStructuredText parser 1 # minirst.py - minimal reStructuredText parser
2 # 2 #
3 # Copyright 2009 Matt Mackall <mpm@selenic.com> and others 3 # Copyright 2009, 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.
181 181
182 for block in blocks[i:j]: 182 for block in blocks[i:j]:
183 block['keywidth'] = keywidth 183 block['keywidth'] = keywidth
184 i = j + 1 184 i = j + 1
185 185
186 return blocks
187
188
189 def prunecontainers(blocks, keep):
190 """Prune unwanted containers.
191
192 The blocks must have a 'type' field, i.e., they should have been
193 run through findliteralblocks first.
194 """
195 i = 0
196 while i + 1 < len(blocks):
197 # Searching for a block that looks like this:
198 #
199 # +-------+---------------------------+
200 # | ".. container ::" type |
201 # +---+ |
202 # | blocks |
203 # +-------------------------------+
204 if (blocks[i]['type'] == 'paragraph' and
205 blocks[i]['lines'][0].startswith('.. container::')):
206 indent = blocks[i]['indent']
207 adjustment = blocks[i + 1]['indent'] - indent
208 containertype = blocks[i]['lines'][0][15:]
209 prune = containertype not in keep
210
211 # Always delete "..container:: type" block
212 del blocks[i]
213 j = i
214 while j < len(blocks) and blocks[j]['indent'] > indent:
215 if prune:
216 del blocks[j]
217 i -= 1 # adjust outer index
218 else:
219 blocks[j]['indent'] -= adjustment
220 j += 1
221 i += 1
186 return blocks 222 return blocks
187 223
188 224
189 def findsections(blocks): 225 def findsections(blocks):
190 """Finds sections. 226 """Finds sections.
279 return textwrap.fill(text, width=width, 315 return textwrap.fill(text, width=width,
280 initial_indent=initindent, 316 initial_indent=initindent,
281 subsequent_indent=subindent) 317 subsequent_indent=subindent)
282 318
283 319
284 def format(text, width, indent=0): 320 def format(text, width, indent=0, keep=[]):
285 """Parse and format the text according to width.""" 321 """Parse and format the text according to width."""
286 blocks = findblocks(text) 322 blocks = findblocks(text)
287 for b in blocks: 323 for b in blocks:
288 b['indent'] += indent 324 b['indent'] += indent
289 blocks = findliteralblocks(blocks) 325 blocks = findliteralblocks(blocks)
326 blocks = prunecontainers(blocks, keep)
290 blocks = inlineliterals(blocks) 327 blocks = inlineliterals(blocks)
291 blocks = splitparagraphs(blocks) 328 blocks = splitparagraphs(blocks)
292 blocks = updatefieldlists(blocks) 329 blocks = updatefieldlists(blocks)
293 blocks = findsections(blocks) 330 blocks = findsections(blocks)
294 blocks = addmargins(blocks) 331 blocks = addmargins(blocks)
296 333
297 334
298 if __name__ == "__main__": 335 if __name__ == "__main__":
299 from pprint import pprint 336 from pprint import pprint
300 337
301 def debug(func, blocks): 338 def debug(func, *args):
302 blocks = func(blocks) 339 blocks = func(*args)
303 print "*** after %s:" % func.__name__ 340 print "*** after %s:" % func.__name__
304 pprint(blocks) 341 pprint(blocks)
305 print 342 print
306 return blocks 343 return blocks
307 344
308 text = open(sys.argv[1]).read() 345 text = open(sys.argv[1]).read()
309 blocks = debug(findblocks, text) 346 blocks = debug(findblocks, text)
310 blocks = debug(findliteralblocks, blocks) 347 blocks = debug(findliteralblocks, blocks)
348 blocks = debug(prunecontainers, blocks, sys.argv[2:])
311 blocks = debug(inlineliterals, blocks) 349 blocks = debug(inlineliterals, blocks)
312 blocks = debug(splitparagraphs, blocks) 350 blocks = debug(splitparagraphs, blocks)
313 blocks = debug(updatefieldlists, blocks) 351 blocks = debug(updatefieldlists, blocks)
314 blocks = debug(findsections, blocks) 352 blocks = debug(findsections, blocks)
315 blocks = debug(addmargins, blocks) 353 blocks = debug(addmargins, blocks)