diff options
Diffstat (limited to 'lib/python/qmk')
| -rw-r--r-- | lib/python/qmk/cli/c2json.py | 59 | ||||
| -rw-r--r-- | lib/python/qmk/keymap.py | 23 | ||||
| -rw-r--r-- | lib/python/qmk/path.py | 6 | 
3 files changed, 46 insertions, 42 deletions
| diff --git a/lib/python/qmk/cli/c2json.py b/lib/python/qmk/cli/c2json.py index 7f6aca070a..f7f1f2ffba 100644 --- a/lib/python/qmk/cli/c2json.py +++ b/lib/python/qmk/cli/c2json.py @@ -1,45 +1,57 @@  """Generate a keymap.json from a keymap.c file.  """ +import re  import json  from argcomplete.completers import FilesCompleter  from milc import cli -import qmk.keymap  import qmk.path  from qmk.json_encoders import InfoJSONEncoder +from qmk.decorators import automagic_keyboard, automagic_keymap  from qmk.keyboard import keyboard_completer, keyboard_folder +from qmk.keymap import locate_keymap, find_keymap_from_dir, generate_json, c2json as c2json_impl  from qmk.errors import CppError +from qmk.commands import dump_lines  @cli.argument('--no-cpp', arg_only=True, action='store_false', help='Do not use \'cpp\' on keymap.c')  @cli.argument('-o', '--output', arg_only=True, type=qmk.path.normpath, help='File to write to')  @cli.argument('-q', '--quiet', arg_only=True, action='store_true', help="Quiet mode, only output error messages") [email protected]('-kb', '--keyboard', arg_only=True, type=keyboard_folder, completer=keyboard_completer, required=True, help='The keyboard\'s name') [email protected]('-km', '--keymap', arg_only=True, required=True, help='The keymap\'s name') [email protected]('filename', arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file') [email protected]('-kb', '--keyboard', type=keyboard_folder, completer=keyboard_completer, help='The keyboard\'s name') [email protected]('-km', '--keymap', help='The keymap\'s name') [email protected]('filename', nargs='?', type=qmk.path.FileType('r'), arg_only=True, completer=FilesCompleter('.c'), help='keymap.c file')  @cli.subcommand('Creates a keymap.json from a keymap.c file.') +@automagic_keyboard +@automagic_keymap  def c2json(cli):      """Generate a keymap.json from a keymap.c file.      This command uses the `qmk.keymap` module to generate a keymap.json from a keymap.c file. The generated keymap is written to stdout, or to a file if -o is provided.      """ -    if cli.args.filename != '-': -        cli.args.filename = qmk.path.normpath(cli.args.filename) +    filename = cli.args.filename +    keyboard = cli.config.c2json.keyboard +    keymap = cli.config.c2json.keymap -        # Error checking -        if not cli.args.filename.exists(): -            cli.log.error('C file does not exist!') -            cli.print_usage() -            return False +    if filename: +        if not keyboard and not keymap: +            # fallback to inferring keyboard/keymap from path +            (keymap, found_type) = find_keymap_from_dir(filename) +            if found_type == 'keymap_directory': +                keyboard = re.search(fr"keyboards/(.+)/keymaps/{keymap}/.*", filename.as_posix()).group(1) -    # Environment processing -    if cli.args.output == ('-'): -        cli.args.output = None +    elif keyboard and keymap: +        if not filename: +            # fallback to inferring keyboard/keymap from path +            filename = locate_keymap(keyboard, keymap) + +    if not all((filename, keyboard, keymap)): +        cli.log.error('You must supply keyboard and keymap, a path to a keymap.c within qmk_firmware, or absolute filename and keyboard and keymap') +        cli.print_help() +        return False -    # Parse the keymap.c      try: -        keymap_json = qmk.keymap.c2json(cli.args.keyboard, cli.args.keymap, cli.args.filename, use_cpp=cli.args.no_cpp) +        keymap_json = c2json_impl(keyboard, keymap, filename, use_cpp=cli.args.no_cpp)      except CppError as e:          if cli.config.general.verbose:              cli.log.debug('The C pre-processor ran into a fatal error: %s', e) @@ -48,19 +60,14 @@ def c2json(cli):      # Generate the keymap.json      try: -        keymap_json = qmk.keymap.generate_json(keymap_json['keymap'], keymap_json['keyboard'], keymap_json['layout'], keymap_json['layers']) +        keymap_json = generate_json(keymap_json['keymap'], keymap_json['keyboard'], keymap_json['layout'], keymap_json['layers'])      except KeyError:          cli.log.error('Something went wrong. Try to use --no-cpp.')          return False      if cli.args.output: -        cli.args.output.parent.mkdir(parents=True, exist_ok=True) -        if cli.args.output.exists(): -            cli.args.output.replace(cli.args.output.parent / (cli.args.output.name + '.bak')) -        cli.args.output.write_text(json.dumps(keymap_json, cls=InfoJSONEncoder, sort_keys=True)) - -        if not cli.args.quiet: -            cli.log.info('Wrote keymap to %s.', cli.args.output) - +        keymap_lines = [json.dumps(keymap_json, cls=InfoJSONEncoder, sort_keys=True)]      else: -        print(json.dumps(keymap_json)) +        keymap_lines = [json.dumps(keymap_json)] + +    dump_lines(cli.args.output, keymap_lines, cli.args.quiet) diff --git a/lib/python/qmk/keymap.py b/lib/python/qmk/keymap.py index 11e8d39dad..281c53cfda 100644 --- a/lib/python/qmk/keymap.py +++ b/lib/python/qmk/keymap.py @@ -191,16 +191,15 @@ def _strip_any(keycode):      return keycode -def find_keymap_from_dir(): -    """Returns `(keymap_name, source)` for the directory we're currently in. - +def find_keymap_from_dir(*args): +    """Returns `(keymap_name, source)` for the directory provided (or cwd if not specified).      """ -    relative_cwd = qmk.path.under_qmk_firmware() +    relative_path = qmk.path.under_qmk_firmware(*args) -    if relative_cwd and len(relative_cwd.parts) > 1: +    if relative_path and len(relative_path.parts) > 1:          # If we're in `qmk_firmware/keyboards` and `keymaps` is in our path, try to find the keyboard name. -        if relative_cwd.parts[0] == 'keyboards' and 'keymaps' in relative_cwd.parts: -            current_path = Path('/'.join(relative_cwd.parts[1:]))  # Strip 'keyboards' from the front +        if relative_path.parts[0] == 'keyboards' and 'keymaps' in relative_path.parts: +            current_path = Path('/'.join(relative_path.parts[1:]))  # Strip 'keyboards' from the front              if 'keymaps' in current_path.parts and current_path.name != 'keymaps':                  while current_path.parent.name != 'keymaps': @@ -209,13 +208,13 @@ def find_keymap_from_dir():                  return current_path.name, 'keymap_directory'          # If we're in `qmk_firmware/layouts` guess the name from the community keymap they're in -        elif relative_cwd.parts[0] == 'layouts' and is_keymap_dir(relative_cwd): -            return relative_cwd.name, 'layouts_directory' +        elif relative_path.parts[0] == 'layouts' and is_keymap_dir(relative_path): +            return relative_path.name, 'layouts_directory'          # If we're in `qmk_firmware/users` guess the name from the userspace they're in -        elif relative_cwd.parts[0] == 'users': +        elif relative_path.parts[0] == 'users':              # Guess the keymap name based on which userspace they're in -            return relative_cwd.parts[1], 'users_directory' +            return relative_path.parts[1], 'users_directory'      return None, None @@ -657,7 +656,7 @@ def parse_keymap_c(keymap_file, use_cpp=True):      Returns:          a dictionary containing the parsed keymap      """ -    if keymap_file == '-': +    if not isinstance(keymap_file, (Path, str)) or keymap_file == '-':          if use_cpp:              keymap_file = _c_preprocess(None, sys.stdin)          else: diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index 9d248451b8..94582a05e0 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py @@ -19,13 +19,11 @@ def is_keyboard(keyboard_name):          return rules_mk.exists() -def under_qmk_firmware(): +def under_qmk_firmware(path=Path(os.environ['ORIG_CWD'])):      """Returns a Path object representing the relative path under qmk_firmware, or None.      """ -    cwd = Path(os.environ['ORIG_CWD']) -      try: -        return cwd.relative_to(QMK_FIRMWARE) +        return path.relative_to(QMK_FIRMWARE)      except ValueError:          return None | 
