FIX: New a2x (since 8.6.7) options in doxyToX.py
[freefoam.git] / data / utilities / doxyToX.py.in
blob105cd0f0319fd1798c0c1aee6f310b5c4a2908f3
1 #!@PYTHON2_EXECUTABLE@
2 #-------------------------------------------------------------------------------
3 # ______ _ ____ __ __
4 # | ____| _| |_ / __ \ /\ | \/ |
5 # | |__ _ __ ___ ___ / \| | | | / \ | \ / |
6 # | __| '__/ _ \/ _ ( (| |) ) | | |/ /\ \ | |\/| |
7 # | | | | | __/ __/\_ _/| |__| / ____ \| | | |
8 # |_| |_| \___|\___| |_| \____/_/ \_\_| |_|
10 # FreeFOAM: The Cross-Platform CFD Toolkit
12 # Copyright (C) 2008-2012 Michael Wild <themiwi@users.sf.net>
13 # Gerber van der Graaf <gerber_graaf@users.sf.net>
14 #-------------------------------------------------------------------------------
15 # License
16 # This file is part of FreeFOAM.
18 # FreeFOAM is free software: you can redistribute it and/or modify it
19 # under the terms of the GNU General Public License as published by the
20 # Free Software Foundation, either version 3 of the License, or (at your
21 # option) any later version.
23 # FreeFOAM is distributed in the hope that it will be useful, but WITHOUT
24 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 # for more details.
28 # You should have received a copy of the GNU General Public License
29 # along with FreeFOAM. If not, see <http://www.gnu.org/licenses/>.
31 # Script
32 # doxyToX
34 # Description
35 # Converts the documentation comments in the file headers into
36 # various formats (currently manpage and xhtml).
38 #------------------------------------------------------------------------------
40 """Usage: doxyToX@PY_SCRIPT_SUFFIX@ [options] <name> <file>
42 Converts the documentation comments in the file headers into various formats
43 (such as asciidoc, man, pdf, html or xml). If <file> ends on [0-9]+.txt, it
44 is assumed that it is an AsciiDoc source file.
46 Options
47 -------
49 -help Display this help message
50 -f <format> Output format (default to 'manpage'). Possible values
51 are: manpage, xhtml and asciidoc (invalid for AsciiDoc
52 input files)
53 -o <outDir> Put the output in <outDir> instead of the same directory as
54 the source is in.
55 -a <confFile> Specify additional AsciiDoc configuration file to use. The
56 files @FOAM_DATA_DIR@/asciidoc/manpage.conf and
57 @FOAM_DATA_DIR@/asciidoc/html.conf for manpage and xhtml
58 formats, respectively are always used. Can be specified
59 multiple times.
60 -v <version> Use <version> as the version number. Defaults
61 to '@FOAM_VERSION_FULL@'.
62 <name> Name of the man-page to create.
63 <file> The source file to to process.
65 """
67 import imp
68 import sys
69 import os
70 import os.path
71 import re
72 import shutil
73 import tempfile
74 sys.path.insert(0, '@FOAM_PYTHON_DIR@')
75 from FreeFOAM.compat import *
77 # cleanup utility function
78 def _cleanup_generated(files, dirs):
79 for f in files:
80 if os.path.isfile(f):
81 os.remove(f)
82 for d in dirs:
83 if os.path.isdir(d):
84 os.rmdir(d)
86 def _prepare_asciidoc(format, source):
87 if format == 'asciidoc':
88 echo("Error: Input and output cannot be both in AsciiDoc format", file=sys.stderr)
89 sys.exit(1)
90 section = None
91 outName = None
92 # parse the section and the name from the source
93 lines = open(source, 'rt').readlines()
94 for l in lines:
95 m = re.match(r'^=.*\((?P<section>\d+)\)\s*=$', l)
96 if m:
97 section = m.group('section')
98 break
99 i = 0
100 while i < len(lines):
101 l = lines[i]
102 if re.match(r'^NAME$', l):
103 outName = lines[i+2].split()[0]
104 break
105 i += 1
106 if not section:
107 echo("ERROR: '%s' is malformed (no man section number in title)"%source,
108 file=sys.stderr)
109 sys.exit(1)
110 elif not outName:
111 echo("ERROR: '%s' is malformed (does not contain NAME section)"%source,
112 file=sys.stderr)
113 sys.exit(1)
114 if format == 'manpage':
115 # only manpage format creates name from file contents,
116 # all others just strip .txt from the end
117 outName = os.path.join(outDir, outName+'.'+section+outExt)
118 else:
119 outName = os.path.join(outDir, os.path.basename(os.path.splitext(source)[0]))+outExt
120 return section, outName
122 def _prepare_header_comments(format, source):
123 import FreeFOAM.doxyToAsciidoc
124 # parse the header comments
125 doc = FreeFOAM.doxyToAsciidoc.Parser(source).parse()
126 # set up substitutions
127 substitutions = {
128 'arguments': ' '.join(map(lambda x: "'%s'"%x, doc['arguments'])),
129 'author': '\n'.join(doc['author']),
130 'bar': 57*'/',
131 'brief': '\n'.join(doc['brief']),
132 'detailed': '\n'.join(doc['detailed']),
133 'name': name,
134 'name_upper': name.upper(),
135 'optional_text': '',
136 'project': '@PROJECT_NAME@',
137 'project_lower': '@PROJECT_NAME@'.lower(),
138 'project_upper': '@PROJECT_NAME@'.upper(),
139 'section': section,
140 'seealso': '\n'.join(doc['seealso']),
141 'source': source,
142 'usage': '\n'.join(doc['usage']),
143 'version': version,
145 options = []
146 for o, a in doc['options'].items():
147 if a:
148 options.append("[%s '%s']"%(o,a))
149 else:
150 options.append("[%s]"%o)
151 substitutions['options'] = ' '.join(options)
152 if len('@FOAM_EXE_PREFIX@'):
153 substitutions['base_name'] = name.replace('@FOAM_EXE_PREFIX@', '', 1)
154 for s, t in doc['sections'].items():
155 substitutions['optional_text'] += (
156 '\n'.join((s.upper(), len(s)*'-', '')) +
157 '\n'.join(t))
158 # construct output name
159 outName = os.path.join(outDir,
160 '%(name)s.%(section)s'%substitutions)+outExt
162 # set up temporary asciidoc source
163 tmpdir = ''
164 asciidocSource = '%(name)s.%(section)s.txt'%substitutions
165 if format == 'asciidoc':
166 asciidocSource = os.path.join(outDir, asciidocSource)
167 else:
168 tmpdir = tempfile.mkdtemp()
169 asciidocSource = os.path.join(tmpdir, asciidocSource)
170 # write it
171 try:
172 outFile = open(asciidocSource, 'wt')
173 outFile.write("""%(bar)s
174 THIS FILE WAS AUTOMATICALLY GENERATED FROM:
175 %(source)s
176 CHANGES TO THIS FILE WILL BE LOST! EDIT THE
177 ABOVE MENTIONED SOURCE FILE INSTEAD.
178 %(bar)s
179 = %(name_upper)s(%(section)s) =
180 :mansource: %(project)s
181 :manversion: %(version)s
182 :manmanual: %(project)s Manual
184 NAME
185 ----
186 %(name)s - %(brief)s
188 SYNOPSIS
189 --------
190 *%(project_lower)s %(base_name)s* %(arguments)s %(options)s
192 DESCRIPTION
193 -----------
194 %(detailed)s
196 OPTIONS
197 -------
198 %(usage)s
200 %(optional_text)s
202 SEE ALSO
203 --------
204 %(seealso)sAn overview of %(project)s is given in linkff:%(project_lower)s[1].
206 AUTHOR
207 ------
208 %(author)s
209 == %(project_upper)s ==
210 Part of the linkff:%(project_lower)s[1] suite.
212 COPYRIGHT
213 ---------
214 * Copyright (C) 2008-2012 Michael Wild.
215 * Copyright (C) 1991-2010 OpenCFD Ltd.
216 """%substitutions)
217 except:
218 _cleanup_generated([asciidocSource], [tmpdir])
219 raise
220 return asciidocSource, outName
222 def _fake_copy_resources(self, html_files, src_dir, dst_dir, resources=[]):
223 pass
225 # option parsing
226 outDir = '.'
227 version = '@FOAM_VERSION_FULL@'
228 format = 'manpage'
229 outExt = ''
230 customConfigs = []
231 attributes = []
233 args = sys.argv[1:]
234 while len(args) > 0:
235 a = args[0]
236 if a == '-h' or a == '-help':
237 echo(__doc__)
238 sys.exit(0)
239 elif a == '-f':
240 if len(args) < 2:
241 echo('Error: The -f option requires an argument', file=sys.stderr)
242 sys.exit(1)
243 format = args[1]
244 del args[0:2]
245 validformats = ('manpage', 'xhtml', 'asciidoc')
246 if format not in validformats:
247 echo('Error: Invalid format "%s". Must be one of\n %s'%
248 (format, ' '.join(validformats)), file=sys.stderr)
249 sys.exit(1)
250 if format == 'xhtml':
251 outExt = '.html'
252 elif format == 'asciidoc':
253 outExt = '.txt'
254 elif a == '-o':
255 if len(args) < 2:
256 echo('Error: The -o option requires an argument', file=sys.stderr)
257 sys.exit(1)
258 outDir = args[1]
259 del args[0:2]
260 elif a == '-a':
261 if len(args) < 2:
262 echo('Error: The -a option requires an argument', file=sys.stderr)
263 sys.exit(1)
264 customConfigs.append('"%"'%args[1])
265 del args[0:2]
266 elif a == '-v':
267 if len(args) < 2:
268 echo('Error: The -v option requires an argument', file=sys.stderr)
269 sys.exit(1)
270 version = args[1]
271 del args[0:2]
272 else:
273 break
275 if len(args) != 2:
276 echo('Error: the name and input file required arguments', file=sys.stderr)
277 sys.exit(1)
279 name = args[0]
280 source = args[1]
282 if not os.path.isfile(source):
283 echo('Error: "%s" does not exist or is not a file'%source, file=sys.stderr)
284 sys.exit(1)
286 if not os.path.isdir(outDir):
287 echo('Error: "%s" does not exist or is not a directory'%outDir, file=sys.stderr)
288 sys.exit(1)
290 # assemble list of configuration files
291 asciidocConfigs = [
292 '', # empty for formatting
294 xsl_file = None
295 xsltproc_opts = [
296 '--param man.th.title.max.length 100',
297 '--stringparam foam.version.full %s'%version
299 if format == 'manpage':
300 asciidocConfigs.append('"@FOAM_DATA_DIR@/asciidoc/manpage.conf"')
301 elif format == 'xhtml':
302 asciidocConfigs.append('"@FOAM_DATA_DIR@/asciidoc/docbook.conf"')
303 xsl_file = '@FOAM_DATA_DIR@/asciidoc/docbook-xsl/xhtml.xsl'
304 xsltproc_opts.append('--param foam.man.current 1')
305 xsltproc_opts.append('--param foam.doc.have_man 1')
306 if '@FOAM_DOCS_FOR_SF@' == 'ON':
307 xsltproc_opts.append('--param foam.doc.for_sf 1')
308 if '@FOAM_ENABLE_XHTML_GUIDES@' == 'ON':
309 xsltproc_opts.append('--param foam.doc.have_ug 1')
310 if '@FOAM_ENABLE_DOXYGEN_DOCS@' == 'ON':
311 xsltproc_opts.append('--param foam.doc.have_doxy 1')
312 asciidocConfigs.extend(customConfigs)
314 # check whether it is already asciidoc source
315 m = re.search(r'\.txt$', source)
316 if m:
317 is_generated = False
318 asciidocSource = source
319 section, outName = _prepare_asciidoc(format, source)
320 else:
321 is_generated = True
322 section = 1
323 asciidocSource, outName = _prepare_header_comments(format, source)
325 # process the AsciiDoc source
326 if format != 'asciidoc':
327 # load the a2x executble as a module
328 a2xfile = open('@A2X_EXECUTABLE@', 'rt')
329 try:
330 a2xmodule = imp.load_module('a2xmodule', a2xfile, a2xfile.name,
331 (os.path.splitext(a2xfile.name)[1], 'r', imp.PY_SOURCE))
332 finally:
333 a2xfile.close()
334 # set up options for a2x
335 opts = {
336 'backend': None,
337 'backend_opts': '',
338 'doctype': 'manpage',
339 'destination_dir': os.path.abspath(outDir),
340 'format': format,
341 'asciidoc_opts': ' -f '.join(asciidocConfigs),
342 'xsltproc_opts': ' '.join(xsltproc_opts),
343 'asciidoc_file': asciidocSource,
344 'conf_file': None,
345 'verbose': False,
346 'resource_dirs': [],
347 'resources': [],
348 'resource_manifest': None,
349 'attributes': attributes,
350 'epubcheck': False,
351 'icons': False,
352 'icons_dir': None,
353 'keep_artifacts': False,
354 'lynx': False,
355 'no_xmllint': False,
356 'dry_run': False,
357 'stylesheet': '../../css/docbook-xsl.css',
358 'dblatex_opts': '',
359 'fop': False,
360 'fop_opts': '',
361 'xsl_file': xsl_file,
363 # override A2X.copy_resources
364 a2xmodule.A2X.copy_resources = _fake_copy_resources
365 # instantiate A2X class and execute the thing
366 a2x = a2xmodule.A2X(opts)
367 a2xmodule.OPTIONS = a2x
368 a2x.load_conf()
369 a2x.execute()
371 # tidy up
372 if is_generated:
373 _cleanup_generated([asciidocSource], [os.path.dirname(asciidocSource)])
374 # compute the final destination name the output SHOULD have
375 destName = os.path.join(outDir,
376 '%s.%s%s'%(name, section, outExt))
377 # if that doesn't match the output file name, rename it
378 if outName != destName:
379 shutil.move(outName, destName)
381 # ------------------------- vim: set sw=3 sts=3 et: --------------- end-of-file