Mercurial > hg
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) |