OptionDocumentationGenerator.py
Go to the documentation of this file.
1#! /usr/bin/env python3
2#------------------------------------------------------------------------------
3
4import sys
5import argparse
6import os
7import re
8import subprocess
9import base64
10#------------------------------------------------------------------------------
11
12def runCmd(cmd, data=None):
13 if input is None:
14 p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
15 stdout, stderr = p.communicate()
16 else:
17 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
18 stdout, stderr = p.communicate(input=data)
19
20 return stdout.decode('utf-8'), stderr.decode('utf-8'), p.returncode
21#------------------------------------------------------------------------------
22
24 cmd = [cxx, '-E', '-x', 'c++', '-v', '/dev/null']
25 stdout, stderr, retCode = runCmd(cmd)
26
27 m = re.findall('\n (/.*)', stderr)
28
29 includes = []
30
31 for x in m:
32 if -1 != x.find('(framework directory)'):
33 continue
34
35 includes.append('-isystem%s' %(x))
36
37 return includes
38#------------------------------------------------------------------------------
39
40def replaceSource(match):
41 fileName = match.group(2)
42
43 cpp = '<!-- source:%s.cpp -->\n' %(fileName)
44 cpp += '```{.cpp}\n'
45 cpp += open('examples/%s.cpp' %(fileName), 'r').read().strip()
46 cpp += '\n```\n'
47 cpp += '<!-- source-end:%s.cpp -->' %(fileName)
48
49 return cpp
50#------------------------------------------------------------------------------
51
52def cppinsightsLink(code, std='2a', options=''):
53 # currently 20 is not a thing
54 if '20' == std:
55 print('Replacing 20 by 2a')
56 std = '2a'
57
58 # per default use latest standard
59 if '' == std:
60 std = '2a'
61
62 std = 'cpp' + std
63
64 if options:
65 options += ',' + std
66 else:
67 options = std
68
69 return('https://cppinsights.io/lnk?code=%s&insightsOptions=%s&rev=1.0' %(base64.b64encode(code).decode('utf-8'), options))
70#------------------------------------------------------------------------------
71
72def replaceInsights(match, parser, args):
73 cppFileName = match.group(2) + '.cpp'
74
75 insightsPath = args['insights']
76 remainingArgs = args['args']
77 defaultCppStd = '-std=%s'% (args['std'])
78
79 defaultIncludeDirs = getDefaultIncludeDirs(args['cxx'])
80 cpp = '<!-- transformed:%s -->\n' %(cppFileName)
81 cpp += 'Here is the transformed code:\n'
82 cpp += '```{.cpp}\n'
83
84 cmd = [insightsPath, 'examples/%s' %(cppFileName), '--', defaultCppStd, '-m64']
85 stdout, stderr, retCode = runCmd(cmd)
86
87 cpp += stdout
88
89 cppData = open('examples/%s' %(cppFileName), 'r').read().strip().encode('utf-8')
90
91
92 cpp += '\n```\n'
93 cpp += '[Live view](%s)\n' %(cppinsightsLink(cppData))
94 cpp += '<!-- transformed-end:%s -->' %(cppFileName)
95
96 return cpp
97#------------------------------------------------------------------------------
98
99def main():
100 parser = argparse.ArgumentParser(description='Description of your program')
101 parser.add_argument('--insights', help='C++ Insights binary', required=True)
102 parser.add_argument('--cxx', help='C++ compiler to used', default='/usr/local/clang-current/bin/clang++')
103 parser.add_argument('--std', help='C++ Standard to used', default='c++17')
104 parser.add_argument('args', nargs=argparse.REMAINDER)
105 args = vars(parser.parse_args())
106
107 insightsPath = args['insights']
108 remainingArgs = args['args']
109 defaultCppStd = '-std=%s'% (args['std'])
110
111 print(insightsPath)
112 defaultIncludeDirs = getDefaultIncludeDirs(args['cxx'])
113
114 for f in os.listdir('.'):
115 if not f.startswith('opt-') or not f.endswith('.md'):
116 continue
117
118 optionName = os.path.splitext(f)[0][4:].strip()
119
120 data = open(f, 'r').read()
121
122 cppFileName = 'cmdl-examples/%s.cpp' %(optionName)
123
124 cpp = open(cppFileName, 'r').read().strip()
125
126 data = data.replace('%s-source' %(optionName), cpp)
127
128 cmd = [insightsPath, cppFileName, '--%s' %(optionName), '--', defaultCppStd, '-m64']
129 stdout, stderr, retCode = runCmd(cmd)
130
131 data = data.replace('%s-transformed' %(optionName), stdout)
132
133 open(f, 'w').write(data)
134
135 regEx = re.compile('(<!-- source:(.*?).cpp -->(.*?)<!-- source-end:(.*?) -->)', re.DOTALL)
136 regExIns = re.compile('(<!-- transformed:(.*?).cpp -->(.*?)<!-- transformed-end:(.*?) -->)', re.DOTALL)
137
138 for f in os.listdir('examples'):
139 if not f.endswith('.md'):
140 continue
141
142 exampleName = os.path.splitext(f)[0].strip()
143
144 mdFileName = os.path.join('examples', '%s.md' %(exampleName))
145
146 mdData = open(mdFileName, 'r').read()
147
148 mdData = regEx.sub(replaceSource, mdData)
149
150 rpl = lambda match : replaceInsights(match, parser, args)
151 mdData = regExIns.sub(rpl, mdData)
152
153 open(mdFileName, 'w').write(mdData)
154
155#------------------------------------------------------------------------------
156
157sys.exit(main())
158#------------------------------------------------------------------------------
159
cppinsightsLink(code, std='2a', options='')