|  | #!/usr/bin/env python3 | 
|  | # Copyright 2014 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | # Runs 'gn help' and various subhelps, and spits out html. | 
|  | # TODO: | 
|  | # - Handle numbered and dashed lists -> <ol> <ul>. (See "os" and "toolchain"). | 
|  | # - Handle "Arguments:" blocks a bit better (the argument names could be | 
|  | #   distinguished). | 
|  | # - Convert "|blahblah|" to <code>. | 
|  | # - Spit out other similar formats like wiki, markdown, whatever. | 
|  |  | 
|  | import html | 
|  | import subprocess | 
|  | import sys | 
|  |  | 
|  |  | 
|  | def GetOutput(*args): | 
|  | try: | 
|  | return subprocess.check_output([sys.argv[1]] + list(args)) | 
|  | except subprocess.CalledProcessError: | 
|  | return '' | 
|  |  | 
|  |  | 
|  | def ParseTopLevel(out): | 
|  | commands = [] | 
|  | output = [] | 
|  | for line in out.splitlines(): | 
|  | if line.startswith('  '): | 
|  | command, sep, rest = line.partition(':') | 
|  | command = command.strip() | 
|  | is_option = command.startswith('-') | 
|  | output_line = ['<li>'] | 
|  | if not is_option: | 
|  | commands.append(command) | 
|  | output_line.append('<a href="#' + html.escape(command) + '">') | 
|  | output_line.append(html.escape(command)) | 
|  | if not is_option: | 
|  | output_line.append('</a>') | 
|  | output_line.extend([sep + html.escape(rest) + '</li>']) | 
|  | output.append(''.join(output_line)) | 
|  | else: | 
|  | output.append('<h2>' + html.escape(line) + '</h2>') | 
|  | return commands, output | 
|  |  | 
|  |  | 
|  | def ParseCommand(command, out): | 
|  | first_line = True | 
|  | got_example = False | 
|  | output = [] | 
|  | for line in out.splitlines(): | 
|  | if first_line: | 
|  | name, sep, rest = line.partition(':') | 
|  | name = name.strip() | 
|  | output.append('<h3><a name="' + html.escape(command) + '">' + | 
|  | html.escape(name + sep + rest) + '</a></h3>') | 
|  | first_line = False | 
|  | else: | 
|  | if line.startswith('Example'): | 
|  | # Special subsection that's pre-formatted. | 
|  | if got_example: | 
|  | output.append('</pre>') | 
|  | got_example = True | 
|  | output.append('<h4>Example</h4>') | 
|  | output.append('<pre>') | 
|  | elif not line.strip(): | 
|  | output.append('<p>') | 
|  | elif not line.startswith('  ') and line.endswith(':'): | 
|  | # Subsection. | 
|  | output.append('<h4>' + html.escape(line[:-1]) + '</h4>') | 
|  | else: | 
|  | output.append(html.escape(line)) | 
|  | if got_example: | 
|  | output.append('</pre>') | 
|  | return output | 
|  |  | 
|  |  | 
|  | def main(): | 
|  | if len(sys.argv) < 2: | 
|  | print('usage: help_as_html.py <gn_binary>') | 
|  | return 1 | 
|  | header = '''<!DOCTYPE html> | 
|  | <html> | 
|  | <head> | 
|  | <meta name="viewport" content="width=device-width, initial-scale=1"> | 
|  | <style> | 
|  | body { font-family: Arial, sans-serif; font-size: small; } | 
|  | pre { font-family: Consolas, monospace; font-size: small; } | 
|  | #container { margin: 0 auto; max-width: 48rem; width: 90%; } | 
|  | </style> | 
|  | </head> | 
|  | <body> | 
|  | <div id="container"><h1>GN</h1> | 
|  | ''' | 
|  | footer = '</div></body></html>' | 
|  | commands, output = ParseTopLevel(GetOutput('help')) | 
|  | for command in commands: | 
|  | output += ParseCommand(command, GetOutput('help', command)) | 
|  | print(header + '\n'.join(output) + footer) | 
|  | return 0 | 
|  |  | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(main()) |