diff options
Diffstat (limited to 'lib/python/qmk/cli/cformat.py')
| -rw-r--r-- | lib/python/qmk/cli/cformat.py | 65 |
1 files changed, 42 insertions, 23 deletions
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) | ||
