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()