1#!/usr/bin/env python3 2 3import os 4import re 5import argparse 6 7DIR_SCRIPTS = os.path.dirname(__file__) 8REPO_ROOT = os.path.join(DIR_SCRIPTS, "..") 9DIR_CWD = os.getcwd() 10 11 12def fatal(msg): 13 print() 14 print("ERROR! " + msg) 15 exit(1) 16 17 18def get_args(): 19 parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter, description="" 20 "Update the configuration file of your existing project based on default parameters and latest LVGL template. Eg.:\n" 21 " python3 generate_lv_conf.py ./src \n" 22 " python3 generate_lv_conf.py --template modules/lvgl/lv_conf_template.h ./my_config_folder" 23 ) 24 25 parser.add_argument('--template', type=str, default=REPO_ROOT, nargs='?', 26 help='Path of "lv_conf_template.h" file or the folder containing it\n(optional, 1 folder above the python script by default)') 27 28 parser.add_argument('--config', type=str, default=None, nargs='?', 29 help='Path of "lv_conf.h" file (optional)') 30 31 parser.add_argument('--defaults', type=str, default=None, nargs='?', 32 help='Path of "lv_conf.defaults" file (optional)') 33 34 parser.add_argument('target', metavar='target', type=str, default=DIR_CWD, nargs='?', 35 help='Folder containing "lv_conf.h" and "lv_conf.defaults" files\n(optional, current work folder by default)') 36 37 args = parser.parse_args() 38 39 if os.path.isdir(args.template): 40 args.template = os.path.join(args.template, "lv_conf_template.h") 41 42 if not args.config: 43 args.config = os.path.join(args.target, "lv_conf.h") 44 45 if not args.defaults: 46 args.defaults = os.path.join(args.target, "lv_conf.defaults") 47 48 if not os.path.exists(args.template): 49 fatal(f"Template file not found at {args.template}") 50 if not os.path.exists(args.config): 51 fatal(f"User config file not found at {args.config}") 52 if not os.path.exists(args.defaults): 53 fatal(f"User defaults not found at {args.defaults}") 54 55 return args 56 57 58def parse_defaults(path: str): 59 defaults = {} 60 61 with open(path, 'r', encoding='utf-8') as file: 62 for line in file.readlines(): 63 if len(line.strip()) == 0 or line.startswith('#'): 64 continue 65 groups = re.search(r'([A-Z0-9_]+)\s+(.+)', line).groups() 66 defaults[groups[0]] = groups[1] 67 68 return defaults 69 70 71def generate_config(path_destination: str, path_source: str, defaults: dict): 72 with open(path_source, 'r', encoding='utf-8') as f_src: 73 src_lines = f_src.readlines() 74 75 keys_used = set() 76 dst_lines = [] 77 78 for src_line in src_lines: 79 res = re.search(r'#define\s+([A-Z0-9_]+)\s+(.+)', src_line) 80 key = res.groups()[0] if res else None 81 82 if key in defaults.keys(): 83 value = defaults[key] 84 pattern = r'(#define\s+[A-Z0-9_]+\s+)(.+)' 85 repl = r'\g<1>' + value 86 dst_line, _ = re.subn(pattern, repl, src_line) 87 88 if not dst_line: 89 fatal(f"Failed to apply key '{key}' to line '{src_line}'") 90 91 print(f"Applying: {key} = {value}") 92 keys_used.add(key) 93 elif 'Set this to "1" to enable content' in src_line: 94 dst_line = '#if 1 /* Enable content */' 95 else: 96 dst_line = src_line 97 98 dst_lines.append(dst_line) 99 100 if len(keys_used) != len(defaults): 101 unused_keys = [k for k in defaults.keys() if k not in keys_used] 102 fatal('The following keys are deprecated:\n ' + '\n '.join(unused_keys)) 103 104 with open(path_destination, 'w', encoding='utf-8') as f_dst: 105 for dst_line in dst_lines: 106 f_dst.write(dst_line) 107 108 109if __name__ == '__main__': 110 args = get_args() 111 112 print("Template:", args.template) 113 print("User config:", args.config) 114 print("User defaults:", args.defaults) 115 116 defaults = parse_defaults(args.defaults) 117 print(f"Loaded {len(defaults)} defaults") 118 119 generate_config(args.config, args.template, defaults) 120 print() 121 print('New config successfully generated!') 122