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