3 Extracts literal blocks from a ReST document and save them out to files.
5 Each literal block can be typed by placing a string like ``#!<type>`` on the
6 first line of the literal block. This can be done, for example, #to mark some
7 literal blocks as SQL code. Literal blocks that are not typed are #associated to
10 If you only want to output a specific type of literal block, you can decide
11 which one to output by using the -t option. By default, only the generic blocks
16 The author uses for multiple purposes, in a way that reminds him of literate
17 programming. For example, when designing a database schema, an interesting
18 use case is to include the schema in a document that describes the entities
19 in detail, with their intended purpose. The code itself goes in the literal
20 blocks. You can them easily extract the SQL string that contains all the SQL
21 data definitions to setup your database schema.
29 asset_id INTEGER REFERENCES asset(id),
30 date TIMESTAMP WITHOUT TIME ZONE,
36 If you run rst-literals on this text you will get only the literal block under
39 Blocks may also be named. If you mark it up like this::
44 you can use the `` --save-named-blocks `` option to have the blocks extracted to
45 corresponding files. Note that you may just use the name if you like::
53 __author__
= 'Martin Blais <blais@furius.ca>'
59 from docutils
import core
, nodes
62 class Visitor(nodes
.SparseNodeVisitor
):
64 def __init__(self
, *args
):
65 nodes
.SparseNodeVisitor
.__init
__(self
, *args
)
68 def visit_literal_block(self
, node
):
70 mo
= re
.match(u
'[ \t]*#!([^ \t]*)([ \t](.*))?\n', text
)
72 typ
, name
= mo
.group(1, 3)
73 text
= text
[mo
.end(3):]
75 typ
, name
= 'generic', None
77 self
.chunks
.append( (typ
, name
, text
) )
81 parser
= optparse
.OptionParser(__doc__
.strip())
83 parser
.add_option('-t', '--type', action
='store',
85 help="Chunk type to extract")
87 parser
.add_option('-s', '--save-named-blocks', action
='store_true',
88 help="Save all named blocks to files (in CWD).")
90 opts
, args
= parser
.parse_args()
93 parser
.error("You must specify a filename to process.")
96 text
= open(fn
).read()
97 document
= core
.publish_doctree(
100 reader_name
='standalone',
101 parser_name
='restructuredtext',
103 'input_encoding': 'UTF-8',
107 v
= Visitor(document
)
110 for typ
, name
, text
in v
.chunks
:
111 if opts
.type and typ
!= opts
.type:
113 output_text(text
, sys
.stdout
)
115 for typ
, name
, text
in v
.chunks
:
116 if name
and opts
.save_named_blocks
:
117 output_text(text
, open(name
, 'w'))
120 def output_text(text
, ss
):
121 "Write out the string 'text' as a block to stream 'ss')."
129 if __name__
== '__main__':