File: script_docs_to_cpp.py

package info (click to toggle)
copyq 13.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,964 kB
  • sloc: cpp: 63,306; sh: 992; xml: 452; python: 293; ruby: 152; makefile: 27; javascript: 25
file content (101 lines) | stat: -rwxr-xr-x 2,897 bytes parent folder | download
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()