2019-07-15 12:14:27 -07:00
|
|
|
"""Functions that help you work with QMK keymaps.
|
|
|
|
|
"""
|
|
|
|
|
import os
|
CLI: add support for list_keymaps
List all the available keymaps for a given keyboard
Add bs4 to requirements.txt
UnicodeDammit is needed from bs4 for reading files.
Major update to work better with revisions
Find the community keymaps supported by each revision.
Get all buildable keymaps for each revision
The command now return all keymaps that's buildable for a
keyboard/revision. If the base directory of a keyboard does not contain
a 'rules.mk' file, nothing is returned. If the base directory contains a
'keymaps' directory, those keycaps will be returned for every revision.
Fix help message.
Try to figure out revision, drop -rv/--revision argument
Fix output format
Another major refactoring, add documentation
Move all useful functions to the qmk module and use the cli subcommand
as a wrapper around it.
Add both inline comments and documentation.
Add test for list_keymaps
Fix regex for parsing rules.mk files
I don't know why it couldn't put it together before... ¯\_(ツ)_/¯
Drop bs4 dependency, update docs, minor improvements
Return only the unique keymaps
Fix merging community and base keymaps
Major rework, no regex/globbing, more walking
Instead of using regexes and globbing to find the rules.mk and keymap.c
files, walk the directory tree to find them.
Also, do away with the concept of revision.
Fix commandline parsing and flake8 findings, rebase
Fixed commandline and config parsing. Thx @xplusplus.
Rebased on master and fixed merge conflicts.
Code cleanup, use pathlib, use pytest keyboard
Clean up checks and logics that are unnecessary due to MILC updates.
Use pathlib instead of os.path for readability.
Use the 'pytest' keyboard for the tests.
Add community layout for 'handwired/onekey/pytest' so we can test
community layouts.
Pathlib-ify qmk.keymap.list_keymaps()
fix list_keymaps for python 3.5
2019-10-08 21:50:21 +02:00
|
|
|
from pathlib import Path
|
2019-07-15 12:14:27 -07:00
|
|
|
|
|
|
|
|
import qmk.path
|
CLI: add support for list_keymaps
List all the available keymaps for a given keyboard
Add bs4 to requirements.txt
UnicodeDammit is needed from bs4 for reading files.
Major update to work better with revisions
Find the community keymaps supported by each revision.
Get all buildable keymaps for each revision
The command now return all keymaps that's buildable for a
keyboard/revision. If the base directory of a keyboard does not contain
a 'rules.mk' file, nothing is returned. If the base directory contains a
'keymaps' directory, those keycaps will be returned for every revision.
Fix help message.
Try to figure out revision, drop -rv/--revision argument
Fix output format
Another major refactoring, add documentation
Move all useful functions to the qmk module and use the cli subcommand
as a wrapper around it.
Add both inline comments and documentation.
Add test for list_keymaps
Fix regex for parsing rules.mk files
I don't know why it couldn't put it together before... ¯\_(ツ)_/¯
Drop bs4 dependency, update docs, minor improvements
Return only the unique keymaps
Fix merging community and base keymaps
Major rework, no regex/globbing, more walking
Instead of using regexes and globbing to find the rules.mk and keymap.c
files, walk the directory tree to find them.
Also, do away with the concept of revision.
Fix commandline parsing and flake8 findings, rebase
Fixed commandline and config parsing. Thx @xplusplus.
Rebased on master and fixed merge conflicts.
Code cleanup, use pathlib, use pytest keyboard
Clean up checks and logics that are unnecessary due to MILC updates.
Use pathlib instead of os.path for readability.
Use the 'pytest' keyboard for the tests.
Add community layout for 'handwired/onekey/pytest' so we can test
community layouts.
Pathlib-ify qmk.keymap.list_keymaps()
fix list_keymaps for python 3.5
2019-10-08 21:50:21 +02:00
|
|
|
import qmk.makefile
|
2019-07-15 12:14:27 -07:00
|
|
|
|
|
|
|
|
# The `keymap.c` template to use when a keyboard doesn't have its own
|
|
|
|
|
DEFAULT_KEYMAP_C = """#include QMK_KEYBOARD_H
|
|
|
|
|
|
|
|
|
|
/* THIS FILE WAS GENERATED!
|
|
|
|
|
*
|
|
|
|
|
* This file was generated by qmk-compile-json. You may or may not want to
|
|
|
|
|
* edit it directly.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
|
|
|
|
__KEYMAP_GOES_HERE__
|
|
|
|
|
};
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def template(keyboard):
|
|
|
|
|
"""Returns the `keymap.c` template for a keyboard.
|
|
|
|
|
|
|
|
|
|
If a template exists in `keyboards/<keyboard>/templates/keymap.c` that
|
|
|
|
|
text will be used instead of `DEFAULT_KEYMAP_C`.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
keyboard
|
|
|
|
|
The keyboard to return a template for.
|
|
|
|
|
"""
|
2020-02-17 11:42:11 -08:00
|
|
|
template_file = Path('keyboards/%s/templates/keymap.c' % keyboard)
|
2019-07-15 12:14:27 -07:00
|
|
|
|
2020-02-17 11:42:11 -08:00
|
|
|
if template_file.exists():
|
|
|
|
|
return template_file.read_text()
|
2019-07-15 12:14:27 -07:00
|
|
|
|
|
|
|
|
return DEFAULT_KEYMAP_C
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate(keyboard, layout, layers):
|
|
|
|
|
"""Returns a keymap.c for the specified keyboard, layout, and layers.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
keyboard
|
|
|
|
|
The name of the keyboard
|
|
|
|
|
|
|
|
|
|
layout
|
|
|
|
|
The LAYOUT macro this keymap uses.
|
|
|
|
|
|
|
|
|
|
layers
|
|
|
|
|
An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
|
|
|
|
|
"""
|
|
|
|
|
layer_txt = []
|
|
|
|
|
for layer_num, layer in enumerate(layers):
|
|
|
|
|
if layer_num != 0:
|
|
|
|
|
layer_txt[-1] = layer_txt[-1] + ','
|
|
|
|
|
layer_keys = ', '.join(layer)
|
|
|
|
|
layer_txt.append('\t[%s] = %s(%s)' % (layer_num, layout, layer_keys))
|
|
|
|
|
|
|
|
|
|
keymap = '\n'.join(layer_txt)
|
2019-07-15 15:12:35 -07:00
|
|
|
keymap_c = template(keyboard)
|
2019-07-15 12:14:27 -07:00
|
|
|
|
|
|
|
|
return keymap_c.replace('__KEYMAP_GOES_HERE__', keymap)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def write(keyboard, keymap, layout, layers):
|
|
|
|
|
"""Generate the `keymap.c` and write it to disk.
|
|
|
|
|
|
|
|
|
|
Returns the filename written to.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
keyboard
|
|
|
|
|
The name of the keyboard
|
|
|
|
|
|
|
|
|
|
keymap
|
|
|
|
|
The name of the keymap
|
|
|
|
|
|
|
|
|
|
layout
|
|
|
|
|
The LAYOUT macro this keymap uses.
|
|
|
|
|
|
|
|
|
|
layers
|
|
|
|
|
An array of arrays describing the keymap. Each item in the inner array should be a string that is a valid QMK keycode.
|
|
|
|
|
"""
|
|
|
|
|
keymap_c = generate(keyboard, layout, layers)
|
2020-02-17 11:42:11 -08:00
|
|
|
keymap_file = qmk.path.keymap(keyboard) / keymap / 'keymap.c'
|
2019-07-15 12:14:27 -07:00
|
|
|
|
2020-02-17 11:42:11 -08:00
|
|
|
keymap_file.parent.mkdir(parents=True, exist_ok=True)
|
|
|
|
|
keymap_file.write_text(keymap_c)
|
2019-07-15 12:14:27 -07:00
|
|
|
|
|
|
|
|
return keymap_file
|
CLI: add support for list_keymaps
List all the available keymaps for a given keyboard
Add bs4 to requirements.txt
UnicodeDammit is needed from bs4 for reading files.
Major update to work better with revisions
Find the community keymaps supported by each revision.
Get all buildable keymaps for each revision
The command now return all keymaps that's buildable for a
keyboard/revision. If the base directory of a keyboard does not contain
a 'rules.mk' file, nothing is returned. If the base directory contains a
'keymaps' directory, those keycaps will be returned for every revision.
Fix help message.
Try to figure out revision, drop -rv/--revision argument
Fix output format
Another major refactoring, add documentation
Move all useful functions to the qmk module and use the cli subcommand
as a wrapper around it.
Add both inline comments and documentation.
Add test for list_keymaps
Fix regex for parsing rules.mk files
I don't know why it couldn't put it together before... ¯\_(ツ)_/¯
Drop bs4 dependency, update docs, minor improvements
Return only the unique keymaps
Fix merging community and base keymaps
Major rework, no regex/globbing, more walking
Instead of using regexes and globbing to find the rules.mk and keymap.c
files, walk the directory tree to find them.
Also, do away with the concept of revision.
Fix commandline parsing and flake8 findings, rebase
Fixed commandline and config parsing. Thx @xplusplus.
Rebased on master and fixed merge conflicts.
Code cleanup, use pathlib, use pytest keyboard
Clean up checks and logics that are unnecessary due to MILC updates.
Use pathlib instead of os.path for readability.
Use the 'pytest' keyboard for the tests.
Add community layout for 'handwired/onekey/pytest' so we can test
community layouts.
Pathlib-ify qmk.keymap.list_keymaps()
fix list_keymaps for python 3.5
2019-10-08 21:50:21 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def list_keymaps(keyboard_name):
|
|
|
|
|
""" List the available keymaps for a keyboard.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
keyboard_name: the keyboards full name with vendor and revision if necessary, example: clueboard/66/rev3
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
a set with the names of the available keymaps
|
|
|
|
|
"""
|
|
|
|
|
# parse all the rules.mk files for the keyboard
|
|
|
|
|
rules_mk = qmk.makefile.get_rules_mk(keyboard_name)
|
|
|
|
|
names = set()
|
|
|
|
|
|
|
|
|
|
if rules_mk:
|
|
|
|
|
# qmk_firmware/keyboards
|
|
|
|
|
keyboards_dir = Path.cwd() / "keyboards"
|
|
|
|
|
# path to the keyboard's directory
|
|
|
|
|
kb_path = keyboards_dir / keyboard_name
|
|
|
|
|
# walk up the directory tree until keyboards_dir
|
|
|
|
|
# and collect all directories' name with keymap.c file in it
|
|
|
|
|
while kb_path != keyboards_dir:
|
|
|
|
|
keymaps_dir = kb_path / "keymaps"
|
|
|
|
|
if keymaps_dir.exists():
|
|
|
|
|
names = names.union([keymap for keymap in os.listdir(str(keymaps_dir)) if (keymaps_dir / keymap / "keymap.c").is_file()])
|
|
|
|
|
kb_path = kb_path.parent
|
|
|
|
|
|
|
|
|
|
# if community layouts are supported, get them
|
|
|
|
|
if "LAYOUTS" in rules_mk:
|
|
|
|
|
for layout in rules_mk["LAYOUTS"].split():
|
|
|
|
|
cl_path = Path.cwd() / "layouts" / "community" / layout
|
|
|
|
|
if cl_path.exists():
|
|
|
|
|
names = names.union([keymap for keymap in os.listdir(str(cl_path)) if (cl_path / keymap / "keymap.c").is_file()])
|
|
|
|
|
|
|
|
|
|
return sorted(names)
|