xref: /btstack/doc/manual/markdown_create_gatt_services_and_clients.py (revision 02d40b2ff04b8cd2ddde0e405dfdc6f00486ec7c)
1#!/usr/bin/env python3
2import os, sys, getopt, re
3import subprocess
4
5class State:
6    SearchIntro = 0
7    IntroFound = 1
8    SearchAPI = 2
9
10mdfiles = {
11    # source file sufix : docu file, [white list od source files]
12    "_server.h" : ["gatt_services.md", ["hids_device.h"]],
13    "_client.h" : ["gatt_clients.md", []]
14}
15
16abrevations = {
17    "Ancs" : "ANCS",
18    "Hids" : "HIDS",
19    "Ublox": "u-blox",
20    "Spp"  : "SPP",
21    "And"  : "and"
22}
23
24description_template = """
25## NAME {#sec:REFERENCE}
26
27"""
28
29description_api = """
30
31See [NAME API](../appendix/apis/#REFERENCE).
32
33"""
34
35def isEmptyCommentLine(line):
36    return re.match(r'(\s*\*\s*)\n',line)
37
38def isCommentLine(line):
39    return re.match(r'(\s*\*\s*).*',line)
40
41def isEndOfComment(line):
42    return re.match(r'\s*\*/.*', line)
43
44def isNewItem(line):
45    return re.match(r'(\s*\*\s*\-\s*)(.*)',line)
46
47def isTextTag(line):
48    return re.match(r'.*(@text).*', line)
49
50def isItemizeTag(line):
51    return re.match(r'(\s+\*\s+)(-\s)(.*)', line)
52
53def processTextLine(line):
54    if isEmptyCommentLine(line):
55        return "\n\n"
56
57    line.rstrip()
58
59    # add missing https://
60    line = line.replace("developer.apple.com","https://developer.apple.com")
61
62    if isTextTag(line):
63        text_line_parts = re.match(r'.*(@text\s*)(.*)', line)
64        return text_line_parts.group(2).lstrip() + " "
65
66    if isItemizeTag(line):
67        text_line_parts = re.match(r'(\s*\*\s*\-\s*)(.*)', line)
68        return "- " + text_line_parts.group(2)
69
70    if isEmptyCommentLine(line):
71        return "\n"
72
73    text_line_parts = re.match(r'(\s+\*\s+)(.*)', line)
74    if text_line_parts:
75        return text_line_parts.group(2) + " "
76    return ""
77
78def handle_abrevations(basename):
79    name_parts = [item.capitalize() for item in basename.split("_")]
80    for i in range(len(name_parts)):
81        try:
82            name_parts[i] = abrevations[name_parts[i]]
83        except KeyError:
84            continue
85
86    return " ".join(name_parts)
87
88
89def process_file(basename, inputfile_path, outputfile_path):
90    reference = basename.replace("_", "-")
91    name = handle_abrevations(basename)
92
93    title = description_template.replace("NAME", name).replace("REFERENCE", reference)
94    api  = description_api.replace("NAME", name).replace("REFERENCE", reference)
95
96    text_block = ""
97    with open(inputfile_path, 'r') as fin:
98        state = State.SearchIntro
99        for line in fin:
100            if state == State.SearchIntro:
101                if isTextTag(line):
102                    state = State.IntroFound
103                    text_block = text_block + processTextLine(line)
104                continue
105
106            if state == State.IntroFound:
107                text_block = text_block + processTextLine(line)
108
109                if isEndOfComment(line):
110                    state = State.SearchIntro
111    fin.close()
112
113    with open(outputfile_path, 'a+') as fout:
114        fout.write(title)
115        fout.write(text_block)
116        fout.write(api)
117    fout.close()
118
119def main(argv):
120    btstackfolder   = os.path.abspath(os.path.dirname(sys.argv[0]) + '/../../')
121    inputfolder     = btstackfolder + "/src/ble/gatt-service/"
122
123    markdownfolder = "docs-markdown/"
124    templatefolder    = "docs-intro/"
125
126    cmd = 'markdown_create_gatt_services_and_clients.py [-r <root_btstackfolder>] [-t <templatefolder>] [-o <output_markdownfolder>]'
127
128    try:
129        opts, args = getopt.getopt(argv,"r:t:o:",["rfolder=","tfolder=","ofolder="])
130    except getopt.GetoptError:
131        print (cmd)
132        sys.exit(2)
133    for opt, arg in opts:
134        if opt == '-h':
135            print (cmd)
136            sys.exit()
137        elif opt in ("-r", "--rfolder"):
138            btstackfolder = arg
139        elif opt in ("-t", "--tfolder"):
140            templatefolder = arg
141        elif opt in ("-o", "--ofolder"):
142            markdownfolder = arg
143
144
145    for source_filename_sufix, [outputfile, white_list] in mdfiles.items():
146        outputfile_path = markdownfolder + outputfile
147        introfile_path = templatefolder + outputfile[:-3] + "_intro.md"
148
149        with open(outputfile_path, 'w') as fout:
150            with open(introfile_path, 'r') as fin:
151                for line in fin:
152                    fout.write(line)
153
154        fin.close()
155        fout.close()
156
157        files_to_process = []
158        for root, dirs, files in os.walk(inputfolder, topdown=True):
159            for f in files:
160                if not f.endswith(source_filename_sufix):
161                    if f not in white_list:
162                        continue
163                files_to_process.append(root + "/"+ f)
164
165        files_to_process.sort()
166
167        for inputfile_path in files_to_process:
168            basename = os.path.basename(inputfile_path)[:-2]
169            process_file(basename, inputfile_path, outputfile_path)
170
171
172if __name__ == "__main__":
173   main(sys.argv[1:])
174