From f4b460c20042b1d04abab1931f81513ac0031c37 Mon Sep 17 00:00:00 2001 From: Akaash Suresh Date: Sat, 22 Feb 2020 22:57:19 -0600 Subject: New functionality for cformat (#7893) Fixing complexity remove lambda PR review fixes #1 Removing unneccesary string substitution Handle -a and specified files Complexity rewrite, use pathlib --- lib/python/qmk/cli/cformat.py | 65 ++++++++++++++++++++----------- lib/python/qmk/path.py | 14 +++++++ lib/python/qmk/tests/test_cli_commands.py | 3 +- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/lib/python/qmk/cli/cformat.py b/lib/python/qmk/cli/cformat.py index de55218ae9..7e3a91dcf0 100644 --- a/lib/python/qmk/cli/cformat.py +++ b/lib/python/qmk/cli/cformat.py @@ -1,16 +1,14 @@ """Format C code according to QMK's style. """ -import os import subprocess from shutil import which from milc import cli +import qmk.path -@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') -@cli.subcommand("Format C code according to QMK's style.") -def cformat(cli): - """Format C code according to QMK's style. +def cformat_run(files, all_files): + """Spawn clang-format subprocess with proper arguments """ # Determine which version of clang-format to use clang_format = ['clang-format', '-i'] @@ -19,27 +17,48 @@ def cformat(cli): if which(binary): clang_format[0] = binary break - - # Find the list of files to format - if cli.args.files: - cli.args.files = [os.path.join(os.environ['ORIG_CWD'], file) for file in cli.args.files] - else: - ignores = ['tmk_core/protocol/usb_hid', 'quantum/template'] - for dir in ['drivers', 'quantum', 'tests', 'tmk_core']: - for dirpath, dirnames, filenames in os.walk(dir): - if any(i in dirpath for i in ignores): - dirnames.clear() - continue - - for name in filenames: - if name.endswith(('.c', '.h', '.cpp')): - cli.args.files.append(os.path.join(dirpath, name)) - - # Run clang-format on the files we've found try: - subprocess.run(clang_format + cli.args.files, check=True) + if not files: + cli.log.warn('No changes detected. Use "qmk cformat -a" to format all files') + return False + if files and all_files: + cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(cli.args.files)) + # 3.6+: Can remove the str casting, python will cast implicitly + subprocess.run(clang_format + [str(file) for file in files], check=True) cli.log.info('Successfully formatted the C code.') except subprocess.CalledProcessError: cli.log.error('Error formatting C code!') return False + + +@cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.') +@cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.') +@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') +@cli.subcommand("Format C code according to QMK's style.") +def cformat(cli): + """Format C code according to QMK's style. + """ + # Empty array for files + files = [] + # Core directories for formatting + core_dirs = ['drivers', 'quantum', 'tests', 'tmk_core'] + ignores = ['tmk_core/protocol/usb_hid', 'quantum/template'] + # Find the list of files to format + if cli.args.files: + files.extend(qmk.path.normpath(file) for file in cli.args.files) + # If -a is specified + elif cli.args.all_files: + all_files = qmk.path.c_source_files(core_dirs) + # The following statement checks each file to see if the file path is in the ignored directories. + files.extend(file for file in all_files if not any(i in str(file) for i in ignores)) + # No files specified & no -a flag + else: + base_args = ['git', 'diff', '--name-only', cli.args.base_branch] + out = subprocess.run(base_args + core_dirs, check=True, stdout=subprocess.PIPE) + changed_files = filter(None, out.stdout.decode('UTF-8').split('\n')) + filtered_files = [qmk.path.normpath(file) for file in changed_files if not any(i in file for i in ignores)] + files.extend(file for file in filtered_files if file.exists() and file.suffix in ['.c', '.h', '.cpp']) + + # Run clang-format on the files we've found + cformat_run(files, cli.args.all_files) diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index d16928afb5..bfaa439249 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py @@ -68,3 +68,17 @@ def normpath(path): return Path(path) return Path(os.environ['ORIG_CWD']) / path + + +def c_source_files(dir_names): + """Returns a list of all *.c, *.h, and *.cpp files for a given list of directories + + Args: + + dir_names + List of directories, relative pathing starts at qmk's cwd + """ + files = [] + for dir in dir_names: + files.extend(file for file in Path(dir).glob('**/*') if file.suffix in ['.c', '.h', '.cpp']) + return files diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index bb77952faf..a2595eb788 100644 --- a/lib/python/qmk/tests/test_cli_commands.py +++ b/lib/python/qmk/tests/test_cli_commands.py @@ -7,7 +7,8 @@ def check_subcommand(command, *args): def test_cformat(): - assert check_subcommand('cformat', 'tmk_core/common/keyboard.c').returncode == 0 + result = check_subcommand('cformat', 'quantum/matrix.c') + assert result.returncode == 0 def test_compile(): -- cgit v1.2.3