16d528ed9Sopenharmony_ci#!/usr/bin/env python3
26d528ed9Sopenharmony_ci# Copyright 2014 The Chromium Authors. All rights reserved.
36d528ed9Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
46d528ed9Sopenharmony_ci# found in the LICENSE file.
56d528ed9Sopenharmony_ci
66d528ed9Sopenharmony_ci# Runs 'gn help' and various subhelps, and spits out html.
76d528ed9Sopenharmony_ci# TODO:
86d528ed9Sopenharmony_ci# - Handle numbered and dashed lists -> <ol> <ul>. (See "os" and "toolchain").
96d528ed9Sopenharmony_ci# - Handle "Arguments:" blocks a bit better (the argument names could be
106d528ed9Sopenharmony_ci#   distinguished).
116d528ed9Sopenharmony_ci# - Convert "|blahblah|" to <code>.
126d528ed9Sopenharmony_ci# - Spit out other similar formats like wiki, markdown, whatever.
136d528ed9Sopenharmony_ci
146d528ed9Sopenharmony_ciimport cgi
156d528ed9Sopenharmony_ciimport subprocess
166d528ed9Sopenharmony_ciimport sys
176d528ed9Sopenharmony_ci
186d528ed9Sopenharmony_ci
196d528ed9Sopenharmony_cidef GetOutput(*args):
206d528ed9Sopenharmony_ci  try:
216d528ed9Sopenharmony_ci    return subprocess.check_output([sys.argv[1]] + list(args))
226d528ed9Sopenharmony_ci  except subprocess.CalledProcessError:
236d528ed9Sopenharmony_ci    return ''
246d528ed9Sopenharmony_ci
256d528ed9Sopenharmony_ci
266d528ed9Sopenharmony_cidef ParseTopLevel(out):
276d528ed9Sopenharmony_ci  commands = []
286d528ed9Sopenharmony_ci  output = []
296d528ed9Sopenharmony_ci  for line in out.splitlines():
306d528ed9Sopenharmony_ci    if line.startswith('  '):
316d528ed9Sopenharmony_ci      command, sep, rest = line.partition(':')
326d528ed9Sopenharmony_ci      command = command.strip()
336d528ed9Sopenharmony_ci      is_option = command.startswith('-')
346d528ed9Sopenharmony_ci      output_line = ['<li>']
356d528ed9Sopenharmony_ci      if not is_option:
366d528ed9Sopenharmony_ci        commands.append(command)
376d528ed9Sopenharmony_ci        output_line.append('<a href="#' + cgi.escape(command) + '">')
386d528ed9Sopenharmony_ci      output_line.append(cgi.escape(command))
396d528ed9Sopenharmony_ci      if not is_option:
406d528ed9Sopenharmony_ci        output_line.append('</a>')
416d528ed9Sopenharmony_ci      output_line.extend([sep + cgi.escape(rest) + '</li>'])
426d528ed9Sopenharmony_ci      output.append(''.join(output_line))
436d528ed9Sopenharmony_ci    else:
446d528ed9Sopenharmony_ci      output.append('<h2>' + cgi.escape(line) + '</h2>')
456d528ed9Sopenharmony_ci  return commands, output
466d528ed9Sopenharmony_ci
476d528ed9Sopenharmony_ci
486d528ed9Sopenharmony_cidef ParseCommand(command, out):
496d528ed9Sopenharmony_ci  first_line = True
506d528ed9Sopenharmony_ci  got_example = False
516d528ed9Sopenharmony_ci  output = []
526d528ed9Sopenharmony_ci  for line in out.splitlines():
536d528ed9Sopenharmony_ci    if first_line:
546d528ed9Sopenharmony_ci      name, sep, rest = line.partition(':')
556d528ed9Sopenharmony_ci      name = name.strip()
566d528ed9Sopenharmony_ci      output.append('<h3><a name="' + cgi.escape(command) + '">' +
576d528ed9Sopenharmony_ci                    cgi.escape(name + sep + rest) + '</a></h3>')
586d528ed9Sopenharmony_ci      first_line = False
596d528ed9Sopenharmony_ci    else:
606d528ed9Sopenharmony_ci      if line.startswith('Example'):
616d528ed9Sopenharmony_ci        # Special subsection that's pre-formatted.
626d528ed9Sopenharmony_ci        if got_example:
636d528ed9Sopenharmony_ci          output.append('</pre>')
646d528ed9Sopenharmony_ci        got_example = True
656d528ed9Sopenharmony_ci        output.append('<h4>Example</h4>')
666d528ed9Sopenharmony_ci        output.append('<pre>')
676d528ed9Sopenharmony_ci      elif not line.strip():
686d528ed9Sopenharmony_ci        output.append('<p>')
696d528ed9Sopenharmony_ci      elif not line.startswith('  ') and line.endswith(':'):
706d528ed9Sopenharmony_ci        # Subsection.
716d528ed9Sopenharmony_ci        output.append('<h4>' + cgi.escape(line[:-1]) + '</h4>')
726d528ed9Sopenharmony_ci      else:
736d528ed9Sopenharmony_ci        output.append(cgi.escape(line))
746d528ed9Sopenharmony_ci  if got_example:
756d528ed9Sopenharmony_ci    output.append('</pre>')
766d528ed9Sopenharmony_ci  return output
776d528ed9Sopenharmony_ci
786d528ed9Sopenharmony_ci
796d528ed9Sopenharmony_cidef main():
806d528ed9Sopenharmony_ci  if len(sys.argv) < 2:
816d528ed9Sopenharmony_ci    print('usage: help_as_html.py <gn_binary>')
826d528ed9Sopenharmony_ci    return 1
836d528ed9Sopenharmony_ci  header = '''<!DOCTYPE html>
846d528ed9Sopenharmony_ci<html>
856d528ed9Sopenharmony_ci  <head>
866d528ed9Sopenharmony_ci    <meta name="viewport" content="width=device-width, initial-scale=1">
876d528ed9Sopenharmony_ci    <style>
886d528ed9Sopenharmony_ci      body { font-family: Arial, sans-serif; font-size: small; }
896d528ed9Sopenharmony_ci      pre { font-family: Consolas, monospace; font-size: small; }
906d528ed9Sopenharmony_ci      #container { margin: 0 auto; max-width: 48rem; width: 90%; }
916d528ed9Sopenharmony_ci    </style>
926d528ed9Sopenharmony_ci  </head>
936d528ed9Sopenharmony_ci  <body>
946d528ed9Sopenharmony_ci    <div id="container"><h1>GN</h1>
956d528ed9Sopenharmony_ci'''
966d528ed9Sopenharmony_ci  footer = '</div></body></html>'
976d528ed9Sopenharmony_ci  commands, output = ParseTopLevel(GetOutput('help'))
986d528ed9Sopenharmony_ci  for command in commands:
996d528ed9Sopenharmony_ci    output += ParseCommand(command, GetOutput('help', command))
1006d528ed9Sopenharmony_ci  print(header + '\n'.join(output) + footer)
1016d528ed9Sopenharmony_ci  return 0
1026d528ed9Sopenharmony_ci
1036d528ed9Sopenharmony_ci
1046d528ed9Sopenharmony_ciif __name__ == '__main__':
1056d528ed9Sopenharmony_ci  sys.exit(main())
106