OptionDocumentationGenerator.py
Go to the documentation of this file.
1 #! /usr/bin/env python3
2 #------------------------------------------------------------------------------
3 
4 import sys
5 import argparse
6 import os
7 import re
8 import subprocess
9 import base64
10 #------------------------------------------------------------------------------
11 
12 def 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 
40 def 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 
52 def 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 
72 def 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 
99 def 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 
157 sys.exit(main())
158 #------------------------------------------------------------------------------
159 
def cppinsightsLink(code, std='2a', options='')
def replaceInsights(match, parser, args)