1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
#!/usr/bin/python2
# vim: fileencoding=utf-8 sw=4 ts=4 et :
# Written by Yeti <yeti@gwyddion.net>. Public domain.
import sys, os, re
# The global mapping between footnote ids (as they appear in the guide) and
# their texts. This is used to compactify footnotes with an identical text.
footnotes = {}
def format_userguide(module, body):
DESCRIPTION, EXTENSIONS, SUPPORTS, NOTES = range(4)
parsesupport = re.compile(r'(?P<name>\w+)'
r'(?::(?P<alias>\w+))?'
r'(?:\[(?P<note>\w+)\])?').match
parsenotes = re.compile(r'(?ms)\[(?P<note>\w+)\]\s*(?P<text>[^[]*)')
entry = ' <entry>%s</entry>'
# Return the local mapping for a footnote (i.e. between [1] in the comment
# in source code and the text that should go to the user guide).
def register_note(footnotes, note):
key, text = note.group('note'), note.group('text').strip()
for fnkey, entry in footnotes.items():
fntext, label = entry
if text == fntext:
fmttext = '<footnoteref linkend="%s" label="%s"/>' \
% (fnkey, label)
return key, fmttext
fnkey = 'table-file-formats-fn%d' % (len(footnotes) + 1)
label = chr(ord('a') + len(footnotes))
fmttext = '<footnote id="%s" label="%s"><para>%s</para></footnote>' \
% (fnkey, label, text)
footnotes[fnkey] = (text, label)
return key, fmttext
def fmtsup(supported, noterefs, what):
yes = 'Yes'
for x in supported:
name = x['name']
if name in what:
if x['alias']:
yes = x['alias']
if x['note']:
yes += noterefs[x['note']]
return yes
return '—'
module = re.sub(r'\.cc?$', '', module)
out = ['<row>']
lines = body.split('\n')[:NOTES]
noterefs = {}
for note in parsenotes.finditer('\n'.join(body.split('\n')[NOTES:])):
key, text = register_note(footnotes, note)
noterefs[key] = text
out.append(entry % lines[DESCRIPTION])
out.append(entry % lines[EXTENSIONS])
out.append(entry % module)
supinfo = [parsesupport(x).groupdict() for x in lines[SUPPORTS].split()]
out.append(entry % fmtsup(supinfo, noterefs, ('Read',)))
out.append(entry % fmtsup(supinfo, noterefs, ('Save', 'Export')))
out.append(entry % fmtsup(supinfo, noterefs, ('SPS',)))
out.append(entry % fmtsup(supinfo, noterefs, ('Volume',)))
out.append('</row>')
for i, x in enumerate(out):
out[i] = ' ' + x
return '\n'.join(out)
mclasses = {
'FREEDESKTOP': {
'comment': '<!-- %s -->',
'header': '''<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>''',
'footer': '</mime-info>'
},
'FILEMAGIC': {
'comment': '# %s',
},
'USERGUIDE': {
'comment': ' <!-- %s -->',
'header': '''<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE book PUBLIC '-//OASIS//DTD DocBook XML V4.5//EN'
'http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd'>
<informaltable id='table-file-formats'>
<indexterm>
<primary>file</primary>
<primary>supported formats</primary>
</indexterm>
<tgroup cols='6' align='left'>
<?dblatex XXlcccc?>
<thead>
<row>
<entry>File Format</entry>
<entry>Extensions</entry>
<entry>Module</entry>
<entry>Read</entry>
<entry>Write</entry>
<entry>SPS</entry>
<entry>Volume</entry>
</row>
</thead>
<tbody>''',
'footer': ''' </tbody>
</tgroup>
</informaltable>''',
'formatter': format_userguide,
},
}
try:
magic = mclasses[sys.argv[1]]
except KeyError:
sys.stderr.write('Unknown magic class %s\n' % sys.argv[1])
sys.exit(1)
except IndexError:
print 'Usage: %s CLASS [FILES...]' % sys.argv[0]
print 'Available classes: %s' % ' '.join(mclasses.keys())
sys.exit(0)
magic_block_re = re.compile(r'(?m)^/\*\*\n \* '
+ r'\[FILE-MAGIC-' + sys.argv[1] + r'\]\n'
+ r'(?P<body>(?: \* .*\n)+) \*\*/$')
output = []
if magic.has_key('header'):
output.append(magic['header'])
# Keep the `GENERATED' string split to prevent match here
output.append(magic['comment'] % ('This is a ' + 'GENERATED' + ' file.'))
for filename in sys.argv[2:]:
base = os.path.basename(filename)
try:
# output From module... comment only if something is found
comment = magic['comment'] % ('From module ' + base)
for m in magic_block_re.finditer(file(filename).read()):
if comment:
output.append(comment)
comment = None
body = re.sub(r'(?m)^ \* ', '', m.group('body'))
if 'formatter' in magic:
body = magic['formatter'](base, body)
output.append(body)
# and when nothing is found, note it
if comment:
comment = magic['comment'] % ('Module %s contains no magic.' % base)
output.append(comment)
except OSError:
sys.stderr.write('Cannot read %s\n' % filename)
sys.exit(1)
if magic.has_key('footer'):
output.append(magic['footer'])
print '\n'.join(output)
|