@ -29,33 +29,37 @@ __KEYMAP_GOES_HERE__
"""
def template ( keyboard , type = ' c ' ) :
""" Returns the `keym ap.c` or `keymap.json` template for a keyboard.
def template_json ( keyboard ) :
""" Returns a `keymap.json` template for a keyboard.
If a template exists in ` keyboards / < keyboard > / templates / keymap . c ` that
text will be used instead of ` DEFAULT_KEYMAP_C ` .
If a template exists in ` keyboards / < keyboard > / templates / keymap . json ` that
text will be used instead of an empty dictionary .
If a template exists in ` keyboards / < keyboard > / templates / keymap . json ` that text will be used instead of an empty dictionary .
Args :
keyboard
The keyboard to return a template for .
"""
template_file = Path ( ' keyboards/ %s /templates/keymap.json ' % keyboard )
template = { ' keyboard ' : keyboard }
if template_file . exists ( ) :
template . update ( json . loads ( template_file . read_text ( ) ) )
return template
type
' json ' for ` keymap . json ` and ' c ' ( or anything else ) for ` keymap . c `
def template_c ( keyboard ) :
""" Returns a `keymap.c` template for a keyboard.
If a template exists in ` keyboards / < keyboard > / templates / keymap . c ` that text will be used instead of an empty dictionary .
Args :
keyboard
The keyboard to return a template for .
"""
if type == ' json ' :
template_file = Path ( ' keyboards/ %s /templates/keymap.json ' % keyboard )
template = { ' keyboard ' : keyboard }
if template_file . exists ( ) :
template . update ( json . loads ( template_file . read_text ( ) ) )
template_file = Path ( ' keyboards/ %s /templates/keymap.c ' % keyboard )
if template_file . exists ( ) :
template = template_file . read_text ( )
else :
template_file = Path ( ' keyboards/ %s /templates/keymap.c ' % keyboard )
if template_file . exists ( ) :
template = template_file . read_text ( )
else :
template = DEFAULT_KEYMAP_C
template = DEFAULT_KEYMAP_C
return template
@ -69,15 +73,65 @@ def _strip_any(keycode):
return keycode
def is_keymap_dir ( keymap ) :
def is_keymap_dir ( keymap , c = True , json = True , additional_files = None ) :
""" Return True if Path object `keymap` has a keymap file inside.
Args :
keymap
A Path ( ) object for the keymap directory you want to check .
c
When true include ` keymap . c ` keymaps .
json
When true include ` keymap . json ` keymaps .
additional_files
A sequence of additional filenames to check against to determine if a directory is a keymap . All files must exist for a match to happen . For example , if you want to match a C keymap with both a ` config . h ` and ` rules . mk ` file : ` is_keymap_dir ( keymap_dir , json = False , additional_files = [ ' config.h ' , ' rules.mk ' ] ) `
"""
for file in ( ' keymap.c ' , ' keymap.json ' ) :
files = [ ]
if c :
files . append ( ' keymap.c ' )
if json :
files . append ( ' keymap.json ' )
for file in files :
if ( keymap / file ) . is_file ( ) :
if additional_files :
for file in additional_files :
if not ( keymap / file ) . is_file ( ) :
return False
return True
def generate ( keyboard , layout , layers , type = ' c ' , keymap = None ) :
def generate_json ( keymap , keyboard , layout , layers ) :
""" Returns a `keymap.json` for the specified keyboard, layout, and layers.
Args :
keymap
A name for this keymap .
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 .
"""
new_keymap = template_json ( keyboard )
new_keymap [ ' keymap ' ] = keymap
new_keymap [ ' layout ' ] = layout
new_keymap [ ' layers ' ] = layers
return new_keymap
def generate_c ( keyboard , layout , layers ) :
""" Returns a `keymap.c` or `keymap.json` for the specified keyboard, layout, and layers.
Args :
@ -89,33 +143,33 @@ def generate(keyboard, layout, layers, type='c', keymap=None):
layers
An array of arrays describing the keymap . Each item in the inner array should be a string that is a valid QMK keycode .
type
' json ' for ` keymap . json ` and ' c ' ( or anything else ) for ` keymap . c `
"""
new_keymap = template ( keyboard , type )
if type == ' json ' :
new_keymap [ ' keymap ' ] = keymap
new_keymap [ ' layout ' ] = layout
new_keymap [ ' layers ' ] = layers
else :
layer_txt = [ ]
for layer_num , layer in enumerate ( layers ) :
if layer_num != 0 :
layer_txt [ - 1 ] = layer_txt [ - 1 ] + ' , '
new_keymap = template_c ( keyboard )
layer_txt = [ ]
for layer_num , layer in enumerate ( layers ) :
if layer_num != 0 :
layer_txt [ - 1 ] = layer_txt [ - 1 ] + ' , '
layer = map ( _strip_any , layer )
layer_keys = ' , ' . join ( layer )
layer_txt . append ( ' \t [ %s ] = %s ( %s ) ' % ( layer_num , layout , layer_keys ) )
keymap = ' \n ' . join ( layer_txt )
new_keymap = new_keymap . replace ( ' __KEYMAP_GOES_HERE__ ' , keymap )
layer = map ( _strip_any , layer )
layer_keys = ' , ' . join ( layer )
layer_txt . append ( ' \t [ %s ] = %s ( %s ) ' % ( layer_num , layout , layer_keys ) )
return new_keymap
keymap = ' \n ' . join ( layer_txt )
new_keymap = new_keymap . replace ( ' __KEYMAP_GOES_HERE__ ' , keymap )
return new_keymap
def write_file ( keymap_filename , keymap_content ) :
keymap_filename . parent . mkdir ( parents = True , exist_ok = True )
keymap_filename . write_text ( keymap_content )
cli . log . info ( ' Wrote keymap to {fg_cyan} %s ' , keymap_filename )
return keymap_filename
def write ( keyboard , keymap , layout , layers , type = ' c ' ) :
""" Generate the `keymap.c` and write it to disk.
def write_json ( keyboard , keymap , layout , layers ) :
""" Generate the `keymap.json` and write it to disk.
Returns the filename written to .
@ -131,23 +185,36 @@ def write(keyboard, keymap, layout, layers, type='c'):
layers
An array of arrays describing the keymap . Each item in the inner array should be a string that is a valid QMK keycode .
type
' json ' for ` keymap . json ` and ' c ' ( or anything else ) for ` keymap . c `
"""
keymap_content = generate ( keyboard , layout , layers , type )
if type == ' json ' :
keymap_file = qmk . path . keymap ( keyboard ) / keymap / ' keymap.json '
keymap_content = json . dumps ( keymap_content )
else :
keymap_file = qmk . path . keymap ( keyboard ) / keymap / ' keymap.c '
keymap_json = generate_json ( keyboard , keymap , layout , layers )
keymap_content = json . dumps ( keymap_json )
keymap_file = qmk . path . keymap ( keyboard ) / keymap / ' keymap.json '
return write_file ( keymap_file , keymap_content )
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_file . parent . mkdir ( parents = True , exist_ok = True )
keymap_file . write_text ( keymap_content )
keymap
The name of the keymap
cli . log . info ( ' Wrote keymap to {fg_cyan} %s ' , keymap_file )
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_content = generate_c ( keyboard , layout , layers )
keymap_file = qmk . path . keymap ( keyboard ) / keymap / ' keymap.c '
return keymap_file
return write_file ( keymap_file , keymap_content )
def locate_keymap ( keyboard , keymap ) :
@ -189,38 +256,58 @@ def locate_keymap(keyboard, keymap):
return community_layout / ' keymap.c '
def list_keymaps ( keyboard ) :
""" List the available keymaps for a keyboard.
def list_keymaps ( keyboard , c = True , json = True , additional_files = None , fullpath = False ) :
""" List the available keymaps for a keyboard.
Args :
keyboard : the keyboards full name with vendor and revision if necessary , example : clueboard / 66 / rev3
keyboard
The keyboards full name with vendor and revision if necessary , example : clueboard / 66 / rev3
c
When true include ` keymap . c ` keymaps .
json
When true include ` keymap . json ` keymaps .
additional_files
A sequence of additional filenames to check against to determine if a directory is a keymap . All files must exist for a match to happen . For example , if you want to match a C keymap with both a ` config . h ` and ` rules . mk ` file : ` is_keymap_dir ( keymap_dir , json = False , additional_files = [ ' config.h ' , ' rules.mk ' ] ) `
fullpath
When set to True the full path of the keymap relative to the ` qmk_firmware ` root will be provided .
Returns :
a set with the names of the available keymaps
a sorted list of valid keymap names .
"""
# parse all the rules.mk files for the keyboard
rules = rules_mk ( keyboard )
names = set ( )
if rules :
# qmk_firmware/keyboards
keyboards_dir = Path ( ' keyboards ' )
# path to the keyboard's directory
kb_path = keyboards_dir / keyboard
# 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 . name for keymap in keymaps_dir . iterdir ( ) if is_keymap_dir ( keymap ) ] )
if keymaps_dir . is_dir ( ) :
for keymap in keymaps_dir . iterdir ( ) :
if is_keymap_dir ( keymap , c , json , additional_files ) :
keymap = keymap if fullpath else keymap . name
names . add ( keymap )
kb_path = kb_path . parent
# if community layouts are supported, get them
if " LAYOUTS " in rules :
for layout in rules [ " LAYOUTS " ] . split ( ) :
cl_path = Path ( ' layouts/community ' ) / layout
if cl_path . exists ( ) :
names = names . union ( [ keymap . name for keymap in cl_path . iterdir ( ) if is_keymap_dir ( keymap ) ] )
if cl_path . is_dir ( ) :
for keymap in cl_path . iterdir ( ) :
if is_keymap_dir ( keymap , c , json , additional_files ) :
keymap = keymap if fullpath else keymap . name
names . add ( keymap )
return sorted ( names )