diff options
Diffstat (limited to 'lib/python')
| -rw-r--r-- | lib/python/qmk/cli/list/keymaps.py | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/lib/python/qmk/cli/list/keymaps.py b/lib/python/qmk/cli/list/keymaps.py index d55ff91fc..2f3014f46 100644 --- a/lib/python/qmk/cli/list/keymaps.py +++ b/lib/python/qmk/cli/list/keymaps.py | |||
| @@ -10,72 +10,77 @@ from milc import cli | |||
| 10 | def unicode_text(filename): | 10 | def unicode_text(filename): |
| 11 | """Returns the contents of filename as a UTF-8 string. Tries to DTRT when it comes to encoding. | 11 | """Returns the contents of filename as a UTF-8 string. Tries to DTRT when it comes to encoding. |
| 12 | """ | 12 | """ |
| 13 | with open(filename, 'rb') as fd: | 13 | with open(filename, "rb") as fd: |
| 14 | text = UnicodeDammit(fd.read()) | 14 | text = UnicodeDammit(fd.read()) |
| 15 | 15 | ||
| 16 | if text.contains_replacement_characters: | 16 | if text.contains_replacement_characters: |
| 17 | log_warning('%s: Could not determine file encoding, some characters were replaced.' % (filename,)) | 17 | log_warning("%s: Could not determine file encoding, some characters were replaced." % (filename,)) |
| 18 | 18 | ||
| 19 | return text.unicode_markup or '' | 19 | return text.unicode_markup or "" |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | def unicode_lines(filename): | 22 | def unicode_lines(filename): |
| 23 | """Returns the contents of filename as a UTF-8 string. Tries to DTRT when it comes to encoding. | 23 | """Returns the contents of filename as a UTF-8 string. Tries to DTRT when it comes to encoding. |
| 24 | """ | 24 | """ |
| 25 | return unicode_text(filename).split('\n') | 25 | return unicode_text(filename).split("\n") |
| 26 | 26 | ||
| 27 | def parse_rules_mk(keyboard): | 27 | def parse_rules_mk(keyboard, revision = ""): |
| 28 | base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep | 28 | base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep |
| 29 | rules_mk_path_wildcard = os.path.join(base_path, "**", "rules.mk") | 29 | rules_mk_path_wildcard = os.path.join(base_path, "**", "rules.mk") |
| 30 | paths = [path for path in glob.iglob(rules_mk_path_wildcard, recursive=True) if "keymaps" not in path] | 30 | rules_mk_regex = re.compile(r"^" + base_path + "(?:" + revision + os.path.sep + ")?rules.mk") |
| 31 | paths = [path for path in glob.iglob(rules_mk_path_wildcard, recursive = True) if rules_mk_regex.search(path)] | ||
| 31 | 32 | ||
| 32 | rules_mk = dict() | 33 | rules_mk = dict() |
| 33 | for file in paths: | 34 | config_regex = re.compile(r"^\s*(\S+)\s*=\s*((?:\s*\S+)+)") |
| 34 | rules_mk_content = unicode_lines(file) | 35 | for file_path in paths: |
| 36 | rules_mk_content = unicode_lines(file_path) | ||
| 35 | parsed_file = dict() | 37 | parsed_file = dict() |
| 36 | for line in rules_mk_content: | 38 | for line in rules_mk_content: |
| 37 | found = re.search(r'^\s*(\w+)\s*=\s*((?:\s*\w+)+)', line) | 39 | found = config_regex.search(line) |
| 38 | if found: | 40 | if found: |
| 39 | parsed_file[found.group(1)] = found.group(2) | 41 | parsed_file[found.group(1)] = found.group(2) |
| 40 | version = file.replace(base_path, "").replace(os.path.sep, "").replace("rules.mk", "") | 42 | version = file_path.replace(base_path, "").replace(os.path.sep, "").replace("rules.mk", "") |
| 41 | rules_mk[version if version else "base"] = parsed_file | 43 | rules_mk[version if version else "base"] = parsed_file |
| 42 | return rules_mk | 44 | return rules_mk |
| 43 | 45 | ||
| 44 | def find_keymaps(base_path, name_finder, community = False): | 46 | def find_keymaps(base_path, revision = "", community = False): |
| 45 | path_wildcard = os.path.join(base_path, "**", "keymap.c") | 47 | path_wildcard = os.path.join(base_path, "**", "keymap.c") |
| 46 | if community: | 48 | if community: |
| 47 | paths = [path for path in glob.iglob(path_wildcard, recursive=True)] | 49 | path_regex = re.compile(r"^" + re.escape(base_path) + "(\S+)" + os.path.sep + "keymap\.c") |
| 50 | names = [revision + os.path.sep + path_regex.sub(lambda name: name.group(1), path) for path in glob.iglob(path_wildcard, recursive = True)] | ||
| 48 | else: | 51 | else: |
| 49 | paths = [path for path in glob.iglob(path_wildcard, recursive=True) if 'keymaps' in path] | 52 | path_regex = re.compile(r"^" + re.escape(base_path) + "(?:" + re.escape(revision) + os.path.sep + ")?keymaps" + os.path.sep + "(\S+)" + os.path.sep + "keymap\.c") |
| 50 | return list(map(name_finder, paths)) | 53 | names = [revision + os.path.sep + path_regex.sub(lambda name: name.group(1), path) if revision else path_regex.sub(lambda name: name.group(1), path) for path in glob.iglob(path_wildcard, recursive = True) if path_regex.search(path)] |
| 54 | return names | ||
| 51 | 55 | ||
| 52 | @cli.argument('-kb', '--keyboard', help='Specify keyboard name. Example: 1upkeyboards/1up60hse') | 56 | @cli.argument("-kb", "--keyboard", help="Specify keyboard name. Example: 1upkeyboards/1up60hse") |
| 57 | @cli.argument("-rv", "--revision", help="Specify the revison name. All revision if not specified. Example: rev6") | ||
| 53 | @cli.subcommand("List the keymaps for a specific keyboard") | 58 | @cli.subcommand("List the keymaps for a specific keyboard") |
| 54 | def list_keymaps(cli): | 59 | def list_keymaps(cli): |
| 55 | """List the keymaps for a specific keyboard | 60 | """List the keymaps for a specific keyboard |
| 56 | """ | 61 | """ |
| 57 | # ask for user input if keyboard was not provided in the command line | 62 | # ask for user input if keyboard was not provided in the command line |
| 58 | keyboard = cli.config.list_keymaps.keyboard if cli.config.list_keymaps.keyboard else input("Keyboard Name: ") | 63 | keyboard = cli.config.list_keymaps.keyboard if cli.config.list_keymaps.keyboard else input("Keyboard Name: ") |
| 59 | 64 | revision = cli.config.list_keymaps.revision if cli.config.list_keymaps.revision else "" | |
| 60 | kb_base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep | ||
| 61 | km_find_name = lambda path: path.replace(kb_base_path, keyboard + os.path.sep).replace("/keymaps/", ":").replace(os.path.sep + "keymap.c", "") | ||
| 62 | names = find_keymaps(kb_base_path, km_find_name) | ||
| 63 | 65 | ||
| 64 | # get all the rules.mk files for the keyboard | 66 | # get all the rules.mk files for the keyboard |
| 65 | rules_mk = parse_rules_mk(keyboard) | 67 | rules_mk = parse_rules_mk(keyboard, revision) |
| 68 | |||
| 69 | if "base" in rules_mk or revision: | ||
| 70 | keyboard_name = keyboard + os.path.sep + revision | ||
| 71 | kb_base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep | ||
| 72 | names = find_keymaps(kb_base_path, revision) | ||
| 73 | else: | ||
| 74 | names = list() | ||
| 66 | 75 | ||
| 67 | for version, data in rules_mk.items(): | 76 | for rev, data in rules_mk.items(): |
| 68 | if "LAYOUTS" in data: | 77 | if "LAYOUTS" in data: |
| 69 | if version == "base": | ||
| 70 | cl_find_name = lambda path: path.replace(cl_base_path, keyboard + ":").replace(os.path.sep + "keymap.c", "") | ||
| 71 | else: | ||
| 72 | cl_find_name = lambda path: path.replace(cl_base_path, keyboard + os.path.sep + version + ":").replace(os.path.sep + "keymap.c", "") | ||
| 73 | for layout in data["LAYOUTS"].split(): | 78 | for layout in data["LAYOUTS"].split(): |
| 74 | cl_base_path = os.path.join(os.getcwd(), "layouts", "community", layout) + os.path.sep | 79 | cl_base_path = os.path.join(os.getcwd(), "layouts", "community", layout) + os.path.sep |
| 75 | names = names + find_keymaps(cl_base_path, cl_find_name, community = True) | 80 | names = names + find_keymaps(cl_base_path, rev, community = True) |
| 76 | 81 | ||
| 77 | names.sort() | 82 | names.sort() |
| 78 | 83 | ||
| 79 | for name in names: | 84 | for name in names: |
| 80 | # We echo instead of cli.log.info to allow easier piping of this output | 85 | # We echo instead of cli.log.info to allow easier piping of this output |
| 81 | cli.echo(name) | 86 | cli.echo(keyboard + os.path.sep + name) |
