1a45ad3caSMarek Kurdej#!/usr/bin/env python3 2a45ad3caSMarek Kurdej# A tool to parse the output of `clang-format --help` and update the 3a45ad3caSMarek Kurdej# documentation in ../ClangFormat.rst automatically. 4a45ad3caSMarek Kurdej 59a5946cdSOwen Panimport argparse 6a45ad3caSMarek Kurdejimport os 7a45ad3caSMarek Kurdejimport re 8a45ad3caSMarek Kurdejimport subprocess 9a45ad3caSMarek Kurdejimport sys 10a45ad3caSMarek Kurdej 11c47c480bSOwenPARENT_DIR = os.path.join(os.path.dirname(__file__), "..") 12c47c480bSOwenDOC_FILE = os.path.join(PARENT_DIR, "ClangFormat.rst") 13a45ad3caSMarek Kurdej 14a45ad3caSMarek Kurdej 15a45ad3caSMarek Kurdejdef substitute(text, tag, contents): 16dd3c26a0STobias Hieta replacement = "\n.. START_%s\n\n%s\n\n.. END_%s\n" % (tag, contents, tag) 17dd3c26a0STobias Hieta pattern = r"\n\.\. START_%s\n.*\n\.\. END_%s\n" % (tag, tag) 18c47c480bSOwen return re.sub(pattern, replacement, text, flags=re.S) 19a45ad3caSMarek Kurdej 20a45ad3caSMarek Kurdej 21a45ad3caSMarek Kurdejdef indent(text, columns, indent_first_line=True): 22dd3c26a0STobias Hieta indent_str = " " * columns 23dd3c26a0STobias Hieta s = re.sub(r"\n([^\n])", "\n" + indent_str + "\\1", text, flags=re.S) 24dd3c26a0STobias Hieta if not indent_first_line or s.startswith("\n"): 25a45ad3caSMarek Kurdej return s 26a45ad3caSMarek Kurdej return indent_str + s 27a45ad3caSMarek Kurdej 28a45ad3caSMarek Kurdej 29a45ad3caSMarek Kurdejdef get_help_output(): 309a5946cdSOwen Pan args = [binary, "--help"] 31dd3c26a0STobias Hieta cmd = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 32a45ad3caSMarek Kurdej out, _ = cmd.communicate() 33a45ad3caSMarek Kurdej out = out.decode(sys.stdout.encoding) 34a45ad3caSMarek Kurdej return out 35a45ad3caSMarek Kurdej 36a45ad3caSMarek Kurdej 37a45ad3caSMarek Kurdejdef get_help_text(): 38a45ad3caSMarek Kurdej out = get_help_output() 39dd3c26a0STobias Hieta out = re.sub(r" clang-format\.exe ", " clang-format ", out) 40a45ad3caSMarek Kurdej 41dd3c26a0STobias Hieta out = ( 42dd3c26a0STobias Hieta """.. code-block:: console 43a45ad3caSMarek Kurdej 44c47c480bSOwen$ clang-format --help 45dd3c26a0STobias Hieta""" 46dd3c26a0STobias Hieta + out 47dd3c26a0STobias Hieta ) 48a45ad3caSMarek Kurdej out = indent(out, 2, indent_first_line=False) 49a45ad3caSMarek Kurdej return out 50a45ad3caSMarek Kurdej 51a45ad3caSMarek Kurdej 52a45ad3caSMarek Kurdejdef validate(text, columns): 53a45ad3caSMarek Kurdej for line in text.splitlines(): 54a45ad3caSMarek Kurdej if len(line) > columns: 55dd3c26a0STobias Hieta print("warning: line too long:\n", line, file=sys.stderr) 56a45ad3caSMarek Kurdej 57a45ad3caSMarek Kurdej 589a5946cdSOwen Panp = argparse.ArgumentParser() 599a5946cdSOwen Panp.add_argument("-d", "--directory", help="directory of clang-format") 60eeadd012SOwen Panp.add_argument("-o", "--output", help="path of output file") 619a5946cdSOwen Panopts = p.parse_args() 629a5946cdSOwen Pan 639a5946cdSOwen Panbinary = "clang-format" 649a5946cdSOwen Panif opts.directory: 659a5946cdSOwen Pan binary = opts.directory + "/" + binary 669a5946cdSOwen Pan 67a45ad3caSMarek Kurdejhelp_text = get_help_text() 68c47c480bSOwenvalidate(help_text, 100) 69a45ad3caSMarek Kurdej 70eeadd012SOwen Panwith open(DOC_FILE, encoding="utf-8") as f: 71a45ad3caSMarek Kurdej contents = f.read() 72a45ad3caSMarek Kurdej 73dd3c26a0STobias Hietacontents = substitute(contents, "FORMAT_HELP", help_text) 74a45ad3caSMarek Kurdej 75*ea44647aSOwen Panwith open( 76*ea44647aSOwen Pan opts.output if opts.output else DOC_FILE, "w", newline="", encoding="utf-8" 77*ea44647aSOwen Pan) as f: 78*ea44647aSOwen Pan f.write(contents) 79