VirtualBox

source: vbox/trunk/doc/manual/build_id_to_file_mapping.py

Last change on this file was 99497, checked in by vboxsync, 12 months ago

manual: Split out the topics of converted manpages into separate files and generate ditamap files for each manpage to avoid needing to hardcode anything in UserManual.xml. This means that the topics inside a manpage can be supressed from the toc, but otoh, they get numbered (with 4.x). The per-topic files are named by refentry/refsect1/refsect2 @id and are currently not cleaned up by 'kmk clean'. bugref:10302

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 4.9 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: build_id_to_file_mapping.py 99497 2023-04-21 01:55:02Z vboxsync $
3
4"""
5Scans the given files (globbed) for topic id and stores records the filename
6in the output file.
7
8This is used by add_file_to_id_only_references.py after converting man_V*.xml
9refentry files to dita to correct links.
10"""
11
12__copyright__ = \
13"""
14Copyright (C) 2023 Oracle and/or its affiliates.
15
16This file is part of VirtualBox base platform packages, as
17available from https://www.virtualbox.org.
18
19This program is free software; you can redistribute it and/or
20modify it under the terms of the GNU General Public License
21as published by the Free Software Foundation, in version 3 of the
22License.
23
24This program is distributed in the hope that it will be useful, but
25WITHOUT ANY WARRANTY; without even the implied warranty of
26MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27General Public License for more details.
28
29You should have received a copy of the GNU General Public License
30along with this program; if not, see <https://www.gnu.org/licenses>.
31
32SPDX-License-Identifier: GPL-3.0-only
33"""
34__version__ = "$Revision: 99497 $"
35
36
37# Standard python imports.
38import glob;
39import os;
40import re;
41import sys;
42
43
44g_oReDita = re.compile(r'<topic[^><]*\sid=("[^">]+"|\'[^\'>]+\')');
45
46def scanDitaFileForIds(dIdToFile, sContent, sFile):
47 """
48 Scans the given content of a .dita-file for topic IDs that can be referenced.
49 """
50 for oMatch in g_oReDita.finditer(sContent):
51 sId = oMatch.group(1)[1:-1];
52 if sId:
53 dIdToFile[sId] = sFile;
54
55g_oReRefentry = re.compile(r'<(refentry\b|refsect[12345]\b|cmdsynopsis\b)[^><]*\sid=("[^">]+"|\'[^\'>]+\')');
56
57def scanDocbookRefentryForIds(dIdToFile, sContent, sFile):
58 """
59 Scans the given content of a Docbook refentry file for topic IDs that can be referenced.
60 """
61 for oMatch in g_oReRefentry.finditer(sContent):
62 sId = oMatch.group(2)[1:-1];
63 if sId:
64 #dIdToFile[sId] = sFile;
65 dIdToFile[sId] = '%s.dita' % (sId,);
66
67def isDocbook(sContent):
68 """
69 Check if the file is a Docbook one.
70 """
71 return sContent.find('<refentry ') >= 0 and sContent.find('<refentryinfo>');
72
73def error(sMessage):
74 """ Reports an error. """
75 print('build_id_to_file_mapping.py: error: %s' % sMessage, file = sys.stderr);
76 return 1;
77
78def syntax(sMessage):
79 """ Reports a syntax error. """
80 print('build_id_to_file_mapping.py: syntax error: %s' % sMessage, file = sys.stderr);
81 return 2;
82
83def usage():
84 """ Reports usage. """
85 print('usage: build_id_to_file_mapping.py --output <map.db> file1.dita docbook2.xml wild*card.* [...]');
86 return 0;
87
88def main(asArgs):
89 """
90 C-like main function.
91 """
92 #
93 # Process arguments.
94 #
95 dIdToFile = {};
96 sOutput = None;
97 fEndOfArgs = False;
98 iArg = 1;
99 while iArg < len(asArgs):
100 sArg = asArgs[iArg];
101 if sArg[0] == '-' and not fEndOfArgs:
102 # Options.
103 if sArg == '--':
104 fEndOfArgs = True;
105 elif sArg in ('--help', '-h', '-?'):
106 return usage();
107 elif sArg in ('--version', '-V' ):
108 print(__version__[__version__.find(':') + 2:-2]);
109 elif sArg in ('--output', '-o'):
110 iArg += 1;
111 if iArg >= len(asArgs):
112 return syntax('Expected filename following "--output"!');
113 sOutput = asArgs[iArg];
114 else:
115 return syntax('Unknown option: %s' % (sArg,));
116 else:
117 # Input files.
118 if sArg[0] == '@':
119 with open(sArg[1:], 'r', encoding = 'utf-8') as oFile:
120 asFiles = oFile.read().split();
121 else:
122 asFiles = glob.glob(sArg);
123 if not asFiles:
124 return error('File not found: %s' % (sArg,));
125 for sFile in asFiles:
126 try:
127 with open(sFile, 'r', encoding = 'utf-8') as oFile:
128 sContent = oFile.read();
129 except Exception as oXcpt: # pylint: disable=broad-exception-caught
130 return error('Failed to open and read "%s": %s' % (sFile, oXcpt,));
131 if isDocbook(sContent):
132 scanDocbookRefentryForIds(dIdToFile, sContent, os.path.splitext(os.path.basename(sFile))[0] + '.dita');
133 else:
134 scanDitaFileForIds(dIdToFile, sContent, os.path.basename(sFile));
135 iArg += 1;
136
137 # Dump the dictionary.
138 asDict = sorted(['%s=%s' % (sKey, sValue) for sKey, sValue in dIdToFile.items()]);
139 if sOutput is not None:
140 try:
141 with open(sOutput, 'w', encoding = 'utf-8') as oFile:
142 oFile.write('\n'.join(asDict));
143 except Exception as oXcpt: # pylint: disable=broad-exception-caught
144 return error('Failed to open and write "%s": %s' % (sFile, oXcpt,));
145 else:
146 sys.stdout.write('\n'.join(asDict));
147 return 0;
148
149if __name__ == "__main__":
150 sys.exit(main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use