99 lines
3.2 KiB
Python
99 lines
3.2 KiB
Python
#!/usr/bin/python
|
|
|
|
# Split source code files into markdown snippets for inclusion in the
|
|
# documentation.
|
|
#
|
|
# Usage: python split-snippets.py TARGET-ROOT INPUT-FILE...
|
|
#
|
|
# Directives in the input files have the form:
|
|
#
|
|
# //+ Directory File-Base-Name
|
|
# lines to be included in
|
|
# the file
|
|
# //-
|
|
#
|
|
# In this example, the lines are written to the file
|
|
# modules/ROOT/pages/_partials/snippets/File-Base-Name.xml under the TARGET-ROOT
|
|
# directory. Whitespace shared with the starting line is stripped.
|
|
# Instead of "//", it is possible to use "#".
|
|
|
|
import re
|
|
import sys
|
|
|
|
target_root = sys.argv[1]
|
|
|
|
def output_file_name(dirname, basename):
|
|
return "{0}/modules/ROOT/pages/_partials/snippets/{1}-{2}.adoc".format(
|
|
target_root, dirname, basename)
|
|
|
|
re_open_file = re.compile(
|
|
r'^(\s*)(?://|#)\+\s+([a-zA-Z0-9_-]+)\s+([a-zA-Z0-9_-]+)\s*\n?$')
|
|
re_close_file = re.compile(r'^\s*(?://|#)\-\s*\n?$')
|
|
|
|
def extension_to_language(path, map={
|
|
'c' : 'C',
|
|
'py' : 'Python',
|
|
'java' : 'Java',
|
|
'sh' : 'Bash',
|
|
}):
|
|
return map.get(path.split('.')[-1], 'C')
|
|
|
|
def write_single_file(path, contents, language):
|
|
assert not [ch for ch in language if ch in "<>&\""]
|
|
with file(path, "w") as out:
|
|
out.write("\n")
|
|
for line in contents:
|
|
for ch in line:
|
|
out.write(ch)
|
|
out.write("\n")
|
|
|
|
def write_output(output):
|
|
for (outpath, (origpath, contents)) in output.items():
|
|
write_single_file(outpath, contents,
|
|
extension_to_language(origpath))
|
|
|
|
def process_file(path):
|
|
output = {}
|
|
with file(path) as f:
|
|
current_file = None
|
|
current_contents = None
|
|
indent = None
|
|
for line in f.readlines():
|
|
match = re_open_file.match(line)
|
|
if match is not None:
|
|
if current_file is None:
|
|
current_file = output_file_name(
|
|
match.group(2), match.group(3))
|
|
if current_file in output:
|
|
raise IOError("{0} written by {1} and {2}",
|
|
current_file, output[current_file][0],
|
|
path)
|
|
indent = match.group(1)
|
|
current_contents = []
|
|
output[current_file] = (path, current_contents)
|
|
else:
|
|
raise IOError("{0}: unterminated export to {1}".format(
|
|
path, current_file))
|
|
continue
|
|
|
|
match = re_close_file.match(line)
|
|
if match is not None:
|
|
if current_file is None:
|
|
raise IOError("{0}: closing file which is not open")
|
|
else:
|
|
current_file = None
|
|
current_contents = None
|
|
indent = None
|
|
continue
|
|
|
|
if current_file is not None:
|
|
if line.startswith(indent):
|
|
line = line[len(indent):]
|
|
current_contents.append(line)
|
|
if current_file is not None:
|
|
raise IOError("{0}: unterminated export to {1}".format(
|
|
path, current_file))
|
|
write_output(output)
|
|
|
|
for path in sys.argv[2:]:
|
|
process_file(path)
|