github.com/Schaudge/grailbase@v0.0.0-20240223061707-44c758a471c0/gtl/generate.py (about)

     1  #!/usr/bin/env python3
     2  
     3  """
     4  Simple template engine.
     5  
     6  Usage:
     7  
     8      generate.py [options] foo.go.tpl
     9  
    10  Example:
    11  
    12      generate.py --prefix=int --PREFIX=Int -DELEM=int32 --package=tests --output=unsafe.go ../unsafe.go.tpl
    13  
    14  --prefix=arg replaces all occurrences of "zz" with "arg".
    15  
    16  --PREFIX=Arg replaces all occurrences of "ZZ" with "Arg". If --Prefix is omitted,
    17    it defaults to --prefix, with its first letter uppercased.
    18  
    19  --Dfrom=to replaces all occurrences of "from" with "to". This flag can be set multiple times.
    20  
    21  --output=path specifies the output file name.
    22  
    23  --goimports=path locates goimports binary. If empty, search on PATH instead.
    24  
    25  --header=str Comment that'll be the first line of the generated file. If empty, use a default.
    26  
    27  """
    28  
    29  import re
    30  import argparse
    31  import subprocess
    32  import sys
    33  
    34  
    35  def main() -> None:
    36      "Main application entry point"
    37      parser = argparse.ArgumentParser()
    38      parser.add_argument(
    39          "--package",
    40          default="funkymonkeypackage",
    41          help="Occurrences of 'PACKAGE' in the template are replaced with this string.",
    42      )
    43      parser.add_argument(
    44          "--prefix",
    45          default="funkymonkey",
    46          help="Occurrences of 'zz'  in the template are replaced with this string",
    47      )
    48      parser.add_argument(
    49          "--PREFIX",
    50          default="",
    51          help="Occurrences of 'ZZ'  in the template are replaced with this string",
    52      )
    53      parser.add_argument(
    54          "-o",
    55          "--output",
    56          default="",
    57          help="Output destination. Defaults to standard output",
    58      )
    59      parser.add_argument(
    60          "-D", "--define", default=[], type=str, action="append", help="str=replacement"
    61      )
    62      parser.add_argument(
    63          "--goimports", default="", help="Path to goimports. Defaults to search PATH",
    64      )
    65      parser.add_argument(
    66          "--header",
    67          default="",
    68          help="First-line comment of the generated file. If empty, generate one.",
    69      )
    70      parser.add_argument("template", help="*.go.tpl file to process")
    71  
    72      opts = parser.parse_args()
    73      if not opts.PREFIX:
    74          if opts.prefix:
    75              opts.PREFIX = opts.prefix[0].upper() + opts.prefix[1:]
    76  
    77      defines = []
    78      for d in opts.define:
    79          m = re.match("^([^=]+)=(.*)", d)
    80          if m is None:
    81              raise Exception("Invalid -D option: " + d)
    82          defines.append((m[1], m[2]))
    83  
    84      out = sys.stdout
    85      if opts.output != "":
    86          out = open(opts.output, "w")
    87      proc = subprocess.Popen(
    88          [opts.goimports or "goimports"],
    89          stdin=subprocess.PIPE,
    90          stdout=out,
    91          universal_newlines=True,
    92      )
    93  
    94      if opts.header:
    95          header = opts.header
    96      else:
    97          header = '// Code generated by "' + " ".join(sys.argv) + '". DO NOT EDIT.\n'
    98      print(header, file=proc.stdin)
    99  
   100      for line in open(opts.template, "r").readlines():
   101          line = line.replace("ZZ", opts.PREFIX)
   102          line = line.replace("zz", opts.prefix)
   103          line = line.replace("PACKAGE", opts.package)
   104          for def_from, def_to in defines:
   105              line = line.replace(def_from, def_to)
   106          print(line, end="", file=proc.stdin)
   107      proc.stdin.close()
   108      status = proc.wait()
   109      if status != 0:
   110          raise Exception("goimports failed: {}".format(status))
   111      if out != sys.stdout:
   112          out.close()
   113  
   114  
   115  main()