Files
qmk_cli-mirror/qmk_cli/script_qmk.py
T
2019-06-30 23:01:33 -07:00

105 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""CLI wrapper for running QMK commands.
This program can be run from anywhere, with or without a qmk_firmware checkout. It provides a small set of subcommands for working with QMK and otherwise dispatches to the `qmk_firmware/bin/qmk` script for the repo you are currently in, or your default repo if you are not currently in a qmk_firmware checkout.
"""
import argparse
import os
import subprocess
import sys
from glob import glob
from time import strftime
from functools import lru_cache
from importlib import import_module
from importlib.util import find_spec
from pathlib import Path
@lru_cache(maxsize=2)
def in_qmk_firmware():
"""Returns the path to the qmk_firmware we are currently in, or None if we are not inside qmk_firmware.
"""
cur_dir = Path.cwd()
while len(cur_dir.parents) > 0:
found_bin = cur_dir / 'bin' / 'qmk'
if found_bin.is_file():
command = [found_bin, '--version']
result = subprocess.run(command)
if result.returncode == 0:
return cur_dir
# Move up a directory before the next iteration
cur_dir = cur_dir / '..'
cur_dir = cur_dir.resolve()
def find_qmk_firmware():
"""Look for qmk_firmware in the usual places.
This function returns the path to qmk_firmware, or the default location if one does not exist.
FIXME(skullydazed): add config file support
"""
if in_qmk_firmware():
return in_qmk_firmware()
if 'QMK_HOME' in os.environ:
return Path(os.environ['QMK_HOME'])
return Path.home() / 'qmk_firmware'
def parse_args():
"""Process arguments outside milc.
"""
parser = argparse.ArgumentParser(description='CLI wrapper for running QMK commands.')
parser.add_argument('-H', '--home', help='Path to the qmk_firmware directory.')
parser.add_argument('subcommand', help='Subcommand to run')
parser.add_argument('subcommand_args', nargs=argparse.REMAINDER, help='Arguments to pass to the subcommand.')
args = parser.parse_args()
if args.home:
os.environ['QMK_HOME'] = args.home
return (args.subcommand, args.subcommand_args)
def main():
"""Dispatch the CLI subcommand to the proper place.
We first check to see if the subcommand was provided by the global `qmk`. If it was we import that module and hand control over to the entrypoint.
All other subcommands are dispatched to the local `qmk`, either the one we are currently in or whatever the user's default qmk_firmware is.
"""
subcommand, subcommand_args = parse_args()
subcommand_module = 'qmk_cli.subcommands.' + subcommand
sys.argv = ['qmk-'+subcommand] + subcommand_args
qmk_firmware = find_qmk_firmware()
qmk_bin = qmk_firmware / 'bin' / 'qmk'
os.environ['QMK_HOME'] = str(qmk_firmware)
try:
# Attempt to import the subcommand from qmk_cli first
import qmk_cli.milc
import_module(subcommand_module)
qmk_cli.milc.cli()
except ModuleNotFoundError as e:
# Check to make sure there's not a bad import statement in qmk_cli
if e.name != subcommand_module:
raise
# Dispatch to the underlying `qmk_firmware/bin/qmk`
if qmk_bin.is_file() and os.access(str(qmk_bin), os.X_OK):
argv = ['python3', str(qmk_bin), subcommand] + subcommand_args
os.execvp('python3', argv)
# Tell the user we can't continue
print('*** Could not locate qmk_firmware directory!')
exit(255)
if __name__ == '__main__':
main()