aboutsummaryrefslogtreecommitdiff
path: root/lib/python/qmk/cli/chibios/confmigrate.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/cli/chibios/confmigrate.py')
-rw-r--r--lib/python/qmk/cli/chibios/confmigrate.py161
1 files changed, 161 insertions, 0 deletions
diff --git a/lib/python/qmk/cli/chibios/confmigrate.py b/lib/python/qmk/cli/chibios/confmigrate.py
new file mode 100644
index 000000000..eae294a0c
--- /dev/null
+++ b/lib/python/qmk/cli/chibios/confmigrate.py
@@ -0,0 +1,161 @@
1"""This script automates the copying of the default keymap into your own keymap.
2"""
3import re
4import sys
5import os
6
7from qmk.constants import QMK_FIRMWARE
8from qmk.path import normpath
9from milc import cli
10
11
12def eprint(*args, **kwargs):
13 print(*args, file=sys.stderr, **kwargs)
14
15
16fileHeader = """\
17/* Copyright 2020 QMK
18 *
19 * This program is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 */
32
33/*
34 * This file was auto-generated by:
35 * `qmk chibios-confupdate -i {0} -r {1}`
36 */
37
38#pragma once
39"""
40
41
42def collect_defines(filepath):
43 with open(filepath, 'r') as f:
44 content = f.read()
45 define_search = re.compile(r'(?m)^#\s*define\s+(?:.*\\\r?\n)*.*$', re.MULTILINE)
46 value_search = re.compile(r'^#\s*define\s+(?P<name>[a-zA-Z0-9_]+(\([^\)]*\))?)\s*(?P<value>.*)', re.DOTALL)
47 define_matches = define_search.findall(content)
48
49 defines = {"keys": [], "dict": {}}
50 for define_match in define_matches:
51 value_match = value_search.search(define_match)
52 defines["keys"].append(value_match.group("name"))
53 defines["dict"][value_match.group("name")] = value_match.group("value")
54 return defines
55
56
57def check_diffs(input_defs, reference_defs):
58 not_present_in_input = []
59 not_present_in_reference = []
60 to_override = []
61
62 for key in reference_defs["keys"]:
63 if key not in input_defs["dict"]:
64 not_present_in_input.append(key)
65 continue
66
67 for key in input_defs["keys"]:
68 if key not in input_defs["dict"]:
69 not_present_in_input.append(key)
70 continue
71
72 for key in input_defs["keys"]:
73 if key in reference_defs["keys"] and input_defs["dict"][key] != reference_defs["dict"][key]:
74 to_override.append((key, input_defs["dict"][key]))
75
76 return (to_override, not_present_in_input, not_present_in_reference)
77
78
79def migrate_chconf_h(to_override, outfile):
80 print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
81
82 for override in to_override:
83 print("#define %s %s" % (override[0], override[1]), file=outfile)
84 print("", file=outfile)
85
86 print("#include_next <chconf.h>\n", file=outfile)
87
88
89def migrate_halconf_h(to_override, outfile):
90 print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
91
92 for override in to_override:
93 print("#define %s %s" % (override[0], override[1]), file=outfile)
94 print("", file=outfile)
95
96 print("#include_next <halconf.h>\n", file=outfile)
97
98
99def migrate_mcuconf_h(to_override, outfile):
100 print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
101
102 print("#include_next <mcuconf.h>\n", file=outfile)
103
104 for override in to_override:
105 print("#undef %s" % (override[0]), file=outfile)
106 print("#define %s %s" % (override[0], override[1]), file=outfile)
107 print("", file=outfile)
108
109
110@cli.argument('-i', '--input', type=normpath, arg_only=True, help='Specify input config file.')
111@cli.argument('-r', '--reference', type=normpath, arg_only=True, help='Specify the reference file to compare against')
112@cli.argument('-o', '--overwrite', arg_only=True, action='store_true', help='Overwrites the input file during migration.')
113@cli.argument('-d', '--delete', arg_only=True, action='store_true', help='If the file has no overrides, migration will delete the input file.')
114@cli.subcommand('Generates a migrated ChibiOS configuration file, as a result of comparing the input against a reference')
115def chibios_confmigrate(cli):
116 """Generates a usable ChibiOS replacement configuration file, based on a fully-defined conf and a reference config.
117 """
118
119 input_defs = collect_defines(cli.args.input)
120 reference_defs = collect_defines(cli.args.reference)
121
122 (to_override, not_present_in_input, not_present_in_reference) = check_diffs(input_defs, reference_defs)
123
124 if len(not_present_in_input) > 0:
125 eprint("Keys not in input, but present inside reference (potential manual migration required):")
126 for key in not_present_in_input:
127 eprint(" %s" % (key))
128
129 if len(not_present_in_reference) > 0:
130 eprint("Keys not in reference, but present inside input (potential manual migration required):")
131 for key in not_present_in_reference:
132 eprint(" %s" % (key))
133
134 if len(to_override) == 0:
135 eprint('No overrides found! If there were no missing keys above, it should be safe to delete the input file.')
136 if cli.args.delete:
137 os.remove(cli.args.input)
138 else:
139 eprint('Overrides found:')
140 for override in to_override:
141 eprint("%40s: %s -> %s" % (override[0], reference_defs["dict"][override[0]].encode('unicode_escape').decode("utf-8"), override[1].encode('unicode_escape').decode("utf-8")))
142
143 eprint('--------------------------------------')
144
145 if "CHCONF_H" in input_defs["dict"] or "_CHCONF_H_" in input_defs["dict"]:
146 migrate_chconf_h(to_override, outfile=sys.stdout)
147 if cli.args.overwrite:
148 with open(cli.args.input, "w") as out_file:
149 migrate_chconf_h(to_override, outfile=out_file)
150
151 elif "HALCONF_H" in input_defs["dict"] or "_HALCONF_H_" in input_defs["dict"]:
152 migrate_halconf_h(to_override, outfile=sys.stdout)
153 if cli.args.overwrite:
154 with open(cli.args.input, "w") as out_file:
155 migrate_halconf_h(to_override, outfile=out_file)
156
157 elif "MCUCONF_H" in input_defs["dict"] or "_MCUCONF_H_" in input_defs["dict"]:
158 migrate_mcuconf_h(to_override, outfile=sys.stdout)
159 if cli.args.overwrite:
160 with open(cli.args.input, "w") as out_file:
161 migrate_mcuconf_h(to_override, outfile=out_file)