Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(539)

Side by Side Diff: ppapi/cpp/documentation/ezt_formatter_c.py

Issue 7030022: Adding documentation directory, new Doxyfile, DoxygenLayout.xml (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/cpp/documentation/DoxygenLayout.xml ('k') | ppapi/cpp/documentation/removefilesC.sh » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python2.4
2 # Copyright 2009, Google Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31
32 """HTML formatter for ezt docs."""
33
34
35 import os
36 import os.path
37 import re
38 import shutil
39 import sys
40
41
42 class DoxygenJavascriptifier(object):
43 """Convert C++ documentation into Javascript style.
44
45 Documentation may be automatically generated using doxygen. However,
46 doxygen only outputs C++ formatted documentation, that is it uses C++
47 conventions for specifying many items even if the java option is selected in
48 the configuration file.
49
50 In order to make the documentation look like Javascript documentation,
51 additional corrections must be made which this class takes care of.
52
53 Since doxygen allows you to name functions and class whatever you wish, this
54 class assumes that you have already chosen to name them with standard
55 Javascript conventions (such as camel-case) and therefore does not try to
56 correct that.
57
58 Though many of the replacements are simply eliminated, they are left as
59 individual items in the dictionary for clarity.
60
61 Attributes:
62 cpp_to_js: a list of c++ to javascript replacement tuples
63 static_function_regex: regular expression describing a static function
64 declaration
65 """
66
67 global_function_tag = '[<a class="doxygen-global">global function</a>]'
68 static_function2_regex = re.compile(r'<li>(.*)static(.*)$')
69 cpp_to_js = [(re.compile(r'::'), '.'),
70 (re.compile(r'\[pure\]'), ''),
71 (re.compile(r'\[pure virtual\]'), ''),
72 (re.compile(r'\[virtual\]'), ''),
73 (re.compile(r'\[protected\]'), ''),
74 (re.compile(r'\[static\]'), global_function_tag),
75 (re.compile(r'\[explicit\]'), ''),
76 (re.compile(r'\bvirtual\b'), ''),
77 (re.compile(r'\bpure\b'), ''),
78 (re.compile(r'\bprotected\b'), ''),
79 (re.compile(r'\bvoid\b'), ''),
80 (re.compile(r'\bunsigned\b'), ''),
81 (re.compile(r'\bstatic\b'), ''),
82 (re.compile(r'\bStatic\b'), 'Global'),
83 (re.compile(r'\bint\b'), 'Number'),
84 (re.compile(r'\bfloat\b'), 'Number'),
85 (re.compile(r'\bNULL\b'), 'null'),
86 (re.compile(r'=0'), ''),
87 # Replace "std.vector<class_name>" with "Array" since vectors
88 # don't exist in Javascript. There is no type for Array in
89 # Javascript.
90 (re.compile(r'std.vector&lt;[\w\s<>"/.=+]*&gt;'), 'Array'),
91 # Remove mention of Vectormath.Aos namespace since it is
92 # invisible to Javascript.
93 (re.compile(r'Vectormath.Aos.Vector3'), 'Vector3'),
94 (re.compile(r'Vectormath.Aos.Vector4'), 'Vector4'),
95 (re.compile(r'Vectormath.Aos.Point3'), 'Point3'),
96 (re.compile(r'Vectormath.Aos.Matrix4'), 'Matrix4'),
97 (re.compile(r'Vectormath.Aos.Quat'), 'Quat'),
98 (re.compile(r'\bconst\b'), '')]
99
100 def Javascriptify(self, lines_list):
101 """Replaces C++-style items with more Javascript-like ones.
102
103 This includes removing many identifiers such as pure, virtual, protected,
104 static and explicit which are not used in Javascript and replacing
105 notation such as '::' with its corresponding Javascript equivalent,
106 '.' in this case.
107
108 Args:
109 lines_list: the list of lines to correct.
110 Returns:
111 the corrected lines in javascript format.
112 """
113 for index, line in enumerate(lines_list):
114 line = self.LabelStaticAsGlobal(line)
115 for cpp_expression, js_expression in self.cpp_to_js:
116 line = re.sub(cpp_expression, js_expression, line)
117 lines_list[index] = line
118 return lines_list
119
120 def LabelStaticAsGlobal(self, line):
121 """If a function is static, we indicate it is a global function.
122
123 Since static does not make sense for Javascript we refer to these
124 functions as global. To designate global function, we place a
125 [global function] tag after the function declaration. Doxygen by
126 default leaves the static descriptor in front of the function so
127 this function looks for the descriptor, removes it and puts the
128 tag at the end.
129
130 Args:
131 line: the line to correct.
132 Returns:
133 the corrected line.
134 """
135 match = re.search(self.static_function2_regex, line)
136 if match is not None:
137 line = '<li>%s%s %s\n' % (match.group(1), match.group(2),
138 self.global_function_tag)
139 return line
140
141
142 class EZTFormatter(object):
143 """This class converts doxygen output into ezt ready files.
144
145 When doxygen outputs files, it contains its own formatting such as adding
146 navigation tabs to the top of each page. This class contains several
147 functions for stripping down doxygen output and formatting doxygen output
148 to be easily parsed by ezt.
149
150 This class assumes that any header/footer boilerplate code (that is code
151 added by the user rather than doxygen at the start or end of a file) is
152 indicated by special indicator strings surrounding it. Namely at the
153 start of boilerplate code: 'BOILERPLATE - DO NOT EDIT THIS BLOCK' and
154 at the end of boilerplate code: 'END OF BOILERPLATE'.
155
156 Attributes:
157 content_start_regex: regular expression for end of boilerplate code
158 content_end_regex: regular expression for start of boilerplate code
159 div_regex: regular expression of html div
160 div_end_regex: regular expression of closing html div
161 navigation_regex: regular expression indicating doxygen navigation tabs
162 html_suffix_regex: regular expression html file suffix
163 current_directory: location of files being worked on
164 originals_directory: directory to store copies of original html files
165 modifiers: list of functions to apply to files passed in
166 """
167 content_start_regex = re.compile('END OF BOILERPLATE')
168 content_end_regex = re.compile('BOILERPLATE - DO NOT EDIT THIS BLOCK')
169 div_regex = re.compile('<div(.*)>')
170 div_end_regex = re.compile('</div>')
171 navigation_regex = re.compile('<div class=\"tabs[0-9]*\"(.*)>')
172 summary_regex = re.compile('<div class=\"summary[0-9]*\"(.*)>')
173 html_suffix_regex = re.compile('\.html$')
174
175 def __init__(self, current_directory):
176
177 self.current_directory = current_directory
178 self.originals_directory = os.path.join(current_directory, 'original_html')
179 if not os.path.exists(self.originals_directory):
180 os.mkdir(self.originals_directory)
181 self.modifiers = []
182
183 def RegisterModifier(self, modifier):
184 """Adds the modifier function to the list of modifier functions.
185
186 Args:
187 modifier: the function modifies a list of strings of code
188 """
189 self.modifiers += [modifier]
190
191 def MakeBackupCopy(self, input_file):
192 """Makes backup copy of input_file by copying to originals directory.
193
194 Args:
195 input_file: basename of file to backup.
196 """
197 shutil.copy(os.path.join(self.current_directory, input_file),
198 self.originals_directory)
199
200 def PerformFunctionsOnFile(self, input_file):
201 """Opens a file as a list, modifies the list and writes to same file.
202
203 Args:
204 input_file: the file being operated on.
205 """
206 infile = open(input_file, 'r')
207 lines_list = infile.readlines()
208 infile.close()
209
210 for function in self.modifiers:
211 lines_list = function(lines_list)
212
213 outfile = open(input_file, 'w')
214 outfile.writelines(lines_list)
215 outfile.close()
216
217 def FixBrackets(self, lines_list):
218 """Adjust brackets to be ezt style.
219
220 Fix the brackets such that any open bracket '[' becomes '[[]' in order to
221 not conflict with the brackets ezt uses as special characters.
222
223 EZT uses boilerplate code at the beginning and end of each file. When
224 editing a file, however, we don't want to touch the boilerplate code.
225 We can look for special indicators through regular expressions of
226 where the content lies between the boilerplate sections and then only
227 apply the desired function line by line to the html between those
228 sections.
229
230 This is a destructive operation and will write over the input file.
231
232 Args:
233 lines_list: the file to fix broken into lines.
234 Returns:
235 the lines_list with correctly formatted brackets.
236 """
237 outside_boilerplate = False
238 for index, line in enumerate(lines_list):
239 if self.content_end_regex.search(line) and outside_boilerplate:
240 # We've reached the end of content; return our work
241 return lines_list
242 elif self.content_start_regex.search(line):
243 # We've found the start of real content, end of boilerplate
244 outside_boilerplate = True
245 elif outside_boilerplate:
246 # Inside real content; fix brackets
247 lines_list[index] = line.replace('[', '[[]')
248 else:
249 pass # Inside boilerplate.
250 return lines_list
251
252 def RemoveNavigation(self, lines_list):
253 """Remove html defining navigation tabs.
254
255 This function removes the lines between the <div class ="tabs">...</div>
256 which will eliminate the navigation tabs Doxygen outputs at the top of
257 its documentation. These are extraneous for Google's codesite which
258 produces its own navigation using the ezt templates.
259
260 Nested <div>'s are handled, but it currently expects no more than one
261 <div>...</div> set per line.
262
263 This is a destructive operation and will write over the input file.
264
265 Args:
266 lines_list: the lines of the file to fix.
267 Returns:
268 the lines_list reformatted to not include tabs div set.
269 """
270 start_index = -1
271 div_queue = []
272 start_end_pairs = {}
273 for index, line in enumerate(lines_list):
274 # Start by looking for the start of the navigation or summary section
275 if self.navigation_regex.search(line) or self.summary_regex.search(line):
276 start_index = index
277 if self.div_regex.search(line):
278 if start_index > -1:
279 div_queue.append(index)
280 if self.div_end_regex.search(line):
281 if start_index > -1:
282 # If we pop our start_index, we have found the matching </div>
283 # to our <div class="tabs">
284 if div_queue.pop() == start_index:
285 start_end_pairs[start_index] = index
286 start_index = -1
287
288 # Delete the offending lines
289 keys = start_end_pairs.keys()
290 keys.sort()
291 keys.reverse()
292 for k in keys:
293 del lines_list[k:start_end_pairs[k]+1]
294 return lines_list
295
296 def RenameFiles(self, input_file):
297 """Fix file suffixes from .html to .ezt.
298
299 This will also backup original html files to the originals directory.
300
301 This operation will overwrite the previous ezt file.
302
303 NOTE: If the originals directory is not a directory, the file will
304 be overwritten.
305
306 Args:
307 input_file: the file to fix.
308 """
309 # If the file does not end in .html, we do not want to continue
310 if self.html_suffix_regex.search(input_file):
311 new_name = re.sub(self.html_suffix_regex, '.ezt', input_file)
312 shutil.copy(input_file, self.originals_directory)
313 # Rename file. If file exists, rename will not overwrite, and produce
314 # OSError. So delete the old file first in that case.
315 try:
316 os.rename(input_file, new_name)
317 except OSError:
318 os.remove(new_name)
319 os.rename(input_file, new_name)
320
321
322 def main():
323 usage_string = ('This script is meant to convert .html files into .ezt files '
324 'in addition to eliminating any C++-style notations and '
325 'replacing them with their Javascript-style counter parts.\n'
326 'Note: This will write over existing files as well as nuke '
327 'any associated directories such as "original_html" located '
328 'in the same directory as the first argument\n'
329 'Usage: ezt_formatter.py <html_file(s)>')
330
331 files = sys.argv[1:]
332 if not files:
333 # We have no files, so return, showing usage
334 print usage_string
335 return
336
337 # current_directory should be the same for all files
338 current_directory = os.path.dirname(files[0])
339 formatter = EZTFormatter(current_directory)
340 #dj = DoxygenJavascriptifier()
341 formatter.RegisterModifier(formatter.RemoveNavigation)
342 #formatter.RegisterModifier(dj.Javascriptify)
343 formatter.RegisterModifier(formatter.FixBrackets)
344
345 for f in files:
346 formatter.PerformFunctionsOnFile(f)
347 formatter.RenameFiles(f)
348
349 formatter.MakeBackupCopy('stylesheet.css')
350
351 if __name__ == '__main__':
352 main()
OLDNEW
« no previous file with comments | « ppapi/cpp/documentation/DoxygenLayout.xml ('k') | ppapi/cpp/documentation/removefilesC.sh » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698