diff options
| author | Akaash Suresh <casa.akaash@gmail.com> | 2020-02-22 22:57:19 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-02-22 20:57:19 -0800 |
| commit | b353028ea5e0ac7b69e7fed4f224c7cb07015ec9 (patch) | |
| tree | b090b1907dff0b47de08d24002e3bcf72f92f8f8 | |
| parent | eb9c2429c69cf034fb3938f0533d15457a2d7820 (diff) | |
| download | qmk_firmware-b353028ea5e0ac7b69e7fed4f224c7cb07015ec9.tar.gz qmk_firmware-b353028ea5e0ac7b69e7fed4f224c7cb07015ec9.zip | |
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
| -rw-r--r-- | docs/cli.md | 26 | ||||
| -rw-r--r-- | lib/python/qmk/cli/cformat.py | 65 | ||||
| -rw-r--r-- | lib/python/qmk/path.py | 14 | ||||
| -rw-r--r-- | lib/python/qmk/tests/test_cli_commands.py | 3 |
4 files changed, 82 insertions, 26 deletions
diff --git a/docs/cli.md b/docs/cli.md index 8ee8ab0e8..7c3effcc0 100644 --- a/docs/cli.md +++ b/docs/cli.md | |||
| @@ -71,14 +71,36 @@ There are some limitations to the local CLI compared to the global CLI: | |||
| 71 | 71 | ||
| 72 | ## `qmk cformat` | 72 | ## `qmk cformat` |
| 73 | 73 | ||
| 74 | This command formats C code using clang-format. Run it with no arguments to format all core code, or pass filenames on the command line to run it on specific files. | 74 | This command formats C code using clang-format. |
| 75 | 75 | ||
| 76 | **Usage**: | 76 | Run it with no arguments to format all core code that has been changed. Default checks `origin/master` with `git diff`, branch can be changed using `-b <branch_name>` |
| 77 | |||
| 78 | Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files. | ||
| 79 | |||
| 80 | **Usage for specified files**: | ||
| 77 | 81 | ||
| 78 | ``` | 82 | ``` |
| 79 | qmk cformat [file1] [file2] [...] [fileN] | 83 | qmk cformat [file1] [file2] [...] [fileN] |
| 80 | ``` | 84 | ``` |
| 81 | 85 | ||
| 86 | **Usage for all core files**: | ||
| 87 | |||
| 88 | ``` | ||
| 89 | qmk cformat -a | ||
| 90 | ``` | ||
| 91 | |||
| 92 | **Usage for only changed files against origin/master**: | ||
| 93 | |||
| 94 | ``` | ||
| 95 | qmk cformat | ||
| 96 | ``` | ||
| 97 | |||
| 98 | **Usage for only changed files against branch_name**: | ||
| 99 | |||
| 100 | ``` | ||
| 101 | qmk cformat -b branch_name | ||
| 102 | ``` | ||
| 103 | |||
| 82 | ## `qmk compile` | 104 | ## `qmk compile` |
| 83 | 105 | ||
| 84 | This command allows you to compile firmware from any directory. You can compile JSON exports from <https://config.qmk.fm>, compile keymaps in the repo, or compile the keyboard in the current working directory. | 106 | This command allows you to compile firmware from any directory. You can compile JSON exports from <https://config.qmk.fm>, compile keymaps in the repo, or compile the keyboard in the current working directory. |
diff --git a/lib/python/qmk/cli/cformat.py b/lib/python/qmk/cli/cformat.py index de55218ae..7e3a91dcf 100644 --- a/lib/python/qmk/cli/cformat.py +++ b/lib/python/qmk/cli/cformat.py | |||
| @@ -1,16 +1,14 @@ | |||
| 1 | """Format C code according to QMK's style. | 1 | """Format C code according to QMK's style. |
| 2 | """ | 2 | """ |
| 3 | import os | ||
| 4 | import subprocess | 3 | import subprocess |
| 5 | from shutil import which | 4 | from shutil import which |
| 6 | 5 | ||
| 7 | from milc import cli | 6 | from milc import cli |
| 7 | import qmk.path | ||
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | @cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') | 10 | def cformat_run(files, all_files): |
| 11 | @cli.subcommand("Format C code according to QMK's style.") | 11 | """Spawn clang-format subprocess with proper arguments |
| 12 | def cformat(cli): | ||
| 13 | """Format C code according to QMK's style. | ||
| 14 | """ | 12 | """ |
| 15 | # Determine which version of clang-format to use | 13 | # Determine which version of clang-format to use |
| 16 | clang_format = ['clang-format', '-i'] | 14 | clang_format = ['clang-format', '-i'] |
| @@ -19,27 +17,48 @@ def cformat(cli): | |||
| 19 | if which(binary): | 17 | if which(binary): |
| 20 | clang_format[0] = binary | 18 | clang_format[0] = binary |
| 21 | break | 19 | break |
| 22 | |||
| 23 | # Find the list of files to format | ||
| 24 | if cli.args.files: | ||
| 25 | cli.args.files = [os.path.join(os.environ['ORIG_CWD'], file) for file in cli.args.files] | ||
| 26 | else: | ||
| 27 | ignores = ['tmk_core/protocol/usb_hid', 'quantum/template'] | ||
| 28 | for dir in ['drivers', 'quantum', 'tests', 'tmk_core']: | ||
| 29 | for dirpath, dirnames, filenames in os.walk(dir): | ||
| 30 | if any(i in dirpath for i in ignores): | ||
| 31 | dirnames.clear() | ||
| 32 | continue | ||
| 33 | |||
| 34 | for name in filenames: | ||
| 35 | if name.endswith(('.c', '.h', '.cpp')): | ||
| 36 | cli.args.files.append(os.path.join(dirpath, name)) | ||
| 37 | |||
| 38 | # Run clang-format on the files we've found | ||
| 39 | try: | 20 | try: |
| 40 | subprocess.run(clang_format + cli.args.files, check=True) | 21 | if not files: |
| 22 | cli.log.warn('No changes detected. Use "qmk cformat -a" to format all files') | ||
| 23 | return False | ||
| 24 | if files and all_files: | ||
| 25 | cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(cli.args.files)) | ||
| 26 | # 3.6+: Can remove the str casting, python will cast implicitly | ||
| 27 | subprocess.run(clang_format + [str(file) for file in files], check=True) | ||
| 41 | cli.log.info('Successfully formatted the C code.') | 28 | cli.log.info('Successfully formatted the C code.') |
| 42 | 29 | ||
| 43 | except subprocess.CalledProcessError: | 30 | except subprocess.CalledProcessError: |
| 44 | cli.log.error('Error formatting C code!') | 31 | cli.log.error('Error formatting C code!') |
| 45 | return False | 32 | return False |
| 33 | |||
| 34 | |||
| 35 | @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.') | ||
| 36 | @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.') | ||
| 37 | @cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') | ||
| 38 | @cli.subcommand("Format C code according to QMK's style.") | ||
| 39 | def cformat(cli): | ||
| 40 | """Format C code according to QMK's style. | ||
| 41 | """ | ||
| 42 | # Empty array for files | ||
| 43 | files = [] | ||
| 44 | # Core directories for formatting | ||
| 45 | core_dirs = ['drivers', 'quantum', 'tests', 'tmk_core'] | ||
| 46 | ignores = ['tmk_core/protocol/usb_hid', 'quantum/template'] | ||
| 47 | # Find the list of files to format | ||
| 48 | if cli.args.files: | ||
| 49 | files.extend(qmk.path.normpath(file) for file in cli.args.files) | ||
| 50 | # If -a is specified | ||
| 51 | elif cli.args.all_files: | ||
| 52 | all_files = qmk.path.c_source_files(core_dirs) | ||
| 53 | # The following statement checks each file to see if the file path is in the ignored directories. | ||
| 54 | files.extend(file for file in all_files if not any(i in str(file) for i in ignores)) | ||
| 55 | # No files specified & no -a flag | ||
| 56 | else: | ||
| 57 | base_args = ['git', 'diff', '--name-only', cli.args.base_branch] | ||
| 58 | out = subprocess.run(base_args + core_dirs, check=True, stdout=subprocess.PIPE) | ||
| 59 | changed_files = filter(None, out.stdout.decode('UTF-8').split('\n')) | ||
| 60 | filtered_files = [qmk.path.normpath(file) for file in changed_files if not any(i in file for i in ignores)] | ||
| 61 | files.extend(file for file in filtered_files if file.exists() and file.suffix in ['.c', '.h', '.cpp']) | ||
| 62 | |||
| 63 | # Run clang-format on the files we've found | ||
| 64 | cformat_run(files, cli.args.all_files) | ||
diff --git a/lib/python/qmk/path.py b/lib/python/qmk/path.py index d16928afb..bfaa43924 100644 --- a/lib/python/qmk/path.py +++ b/lib/python/qmk/path.py | |||
| @@ -68,3 +68,17 @@ def normpath(path): | |||
| 68 | return Path(path) | 68 | return Path(path) |
| 69 | 69 | ||
| 70 | return Path(os.environ['ORIG_CWD']) / path | 70 | return Path(os.environ['ORIG_CWD']) / path |
| 71 | |||
| 72 | |||
| 73 | def c_source_files(dir_names): | ||
| 74 | """Returns a list of all *.c, *.h, and *.cpp files for a given list of directories | ||
| 75 | |||
| 76 | Args: | ||
| 77 | |||
| 78 | dir_names | ||
| 79 | List of directories, relative pathing starts at qmk's cwd | ||
| 80 | """ | ||
| 81 | files = [] | ||
| 82 | for dir in dir_names: | ||
| 83 | files.extend(file for file in Path(dir).glob('**/*') if file.suffix in ['.c', '.h', '.cpp']) | ||
| 84 | return files | ||
diff --git a/lib/python/qmk/tests/test_cli_commands.py b/lib/python/qmk/tests/test_cli_commands.py index bb77952fa..a2595eb78 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): | |||
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | def test_cformat(): | 9 | def test_cformat(): |
| 10 | assert check_subcommand('cformat', 'tmk_core/common/keyboard.c').returncode == 0 | 10 | result = check_subcommand('cformat', 'quantum/matrix.c') |
| 11 | assert result.returncode == 0 | ||
| 11 | 12 | ||
| 12 | 13 | ||
| 13 | def test_compile(): | 14 | def test_compile(): |
