You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.8 KiB

  1. """Format C code according to QMK's style.
  2. """
  3. import subprocess
  4. from shutil import which
  5. from argcomplete.completers import FilesCompleter
  6. from milc import cli
  7. from qmk.path import normpath
  8. from qmk.c_parse import c_source_files
  9. def cformat_run(files, all_files):
  10. """Spawn clang-format subprocess with proper arguments
  11. """
  12. # Determine which version of clang-format to use
  13. clang_format = ['clang-format', '-i']
  14. for clang_version in range(20, 6, -1):
  15. binary = 'clang-format-%d' % clang_version
  16. if which(binary):
  17. clang_format[0] = binary
  18. break
  19. try:
  20. if not files:
  21. cli.log.warn('No changes detected. Use "qmk cformat -a" to format all files')
  22. return False
  23. subprocess.run(clang_format + [file for file in files], check=True)
  24. cli.log.info('Successfully formatted the C code.')
  25. except subprocess.CalledProcessError:
  26. cli.log.error('Error formatting C code!')
  27. return False
  28. @cli.argument('-a', '--all-files', arg_only=True, action='store_true', help='Format all core files.')
  29. @cli.argument('-b', '--base-branch', default='origin/master', help='Branch to compare to diffs to.')
  30. @cli.argument('files', nargs='*', arg_only=True, completer=FilesCompleter('.c'), help='Filename(s) to format.')
  31. @cli.subcommand("Format C code according to QMK's style.", hidden=False if cli.config.user.developer else True)
  32. def cformat(cli):
  33. """Format C code according to QMK's style.
  34. """
  35. # Empty array for files
  36. files = []
  37. # Core directories for formatting
  38. core_dirs = ['drivers', 'quantum', 'tests', 'tmk_core', 'platforms']
  39. ignores = ['tmk_core/protocol/usb_hid', 'quantum/template', 'platforms/chibios']
  40. # Find the list of files to format
  41. if cli.args.files:
  42. files.extend(normpath(file) for file in cli.args.files)
  43. if cli.args.all_files:
  44. cli.log.warning('Filenames passed with -a, only formatting: %s', ','.join(map(str, files)))
  45. # If -a is specified
  46. elif cli.args.all_files:
  47. all_files = c_source_files(core_dirs)
  48. # The following statement checks each file to see if the file path is in the ignored directories.
  49. files.extend(file for file in all_files if not any(i in str(file) for i in ignores))
  50. # No files specified & no -a flag
  51. else:
  52. base_args = ['git', 'diff', '--name-only', cli.args.base_branch]
  53. out = subprocess.run(base_args + core_dirs, check=True, stdout=subprocess.PIPE)
  54. changed_files = filter(None, out.stdout.decode('UTF-8').split('\n'))
  55. filtered_files = [normpath(file) for file in changed_files if not any(i in file for i in ignores)]
  56. files.extend(file for file in filtered_files if file.exists() and file.suffix in ['.c', '.h', '.cpp'])
  57. # Run clang-format on the files we've found
  58. cformat_run(files, cli.args.all_files)