1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#!/usr/bin/python
'''
Parses API for C++ from Scriptable API documentation.
'''
import re
readme_path = 'docs/scripting-api.rst'
output_path = 'src/gui/commandcompleterdocumentation.h'
header = '''// Generated by "utils/script_docs_to_cpp.py" from "%s".
#pragma once
template <typename AddDocumentationCallback>
void addDocumentation(AddDocumentationCallback addDocumentation)
{
'''
footer = '}'
# Regex for function/variable/type name in documentation
re_title = re.compile(r'''
(?:
^\.\.\s*js:function::\s*
(?P<function_api>
# function return value
.*?
# function name
(?P<function_name>[\w.]+)
# arguments
\(.*
)
|
^\.\.\s*js:data::\s*
# variable name
(?P<variable_name>[\w.]+)
|
^\.\.\s*js:class::\s*
# type name
(?P<type_name>[\w.]+)$
)
''', re.VERBOSE)
def write_api(output_file, name, api, description, rtype):
if rtype:
api = f'{api} -> {rtype}'
output = ' addDocumentation("{}", "{}", "{}");\n'\
.format(name, api, description)
output_file.write(output)
def main():
with open(output_path, mode='w', encoding='utf-8') as output_file:
output_file.write((header % readme_path) + '\n')
with open(readme_path, mode='r', encoding='utf-8') as readme_file:
name = None
api = None
description = None
rtype = None
for line in readme_file:
# Skip lines with large indentation, like function aliases.
if line.startswith(' ' * 5):
continue
line = line.strip().replace('``', '`')
line = re.sub(r':js:func:`([^`]+)`', r'`\1()`', line)
line = re.sub(r':js:[^:]*:`([^`]+)`', r'`\1`', line)
line = re.sub(r'/\*[^*]+\*/', r'', line)
match = re.match(re_title, line)
if match:
if name:
write_api(output_file, name, api, description, rtype)
name = match.group('function_name') or match.group('variable_name') or match.group('type_name')
api = match.group('function_api') or name
description = None
rtype = None
elif not description or not description.endswith("."):
if description:
description += " " + line.strip()
else:
description = line.strip()
else:
rtype_match = re.match(r'^\s*:rtype: (?P<rtype>.+)', line)
if rtype_match:
rtype = rtype_match.group('rtype')
if name:
write_api(output_file, name, api, description, rtype)
output_file.write(footer + '\n')
if __name__ == "__main__":
main()
|