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
master
Akaash Suresh 2020-02-22 22:57:19 -06:00 committed by GitHub
parent eb9c2429c6
commit b353028ea5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 26 deletions

View File

@ -71,14 +71,36 @@ There are some limitations to the local CLI compared to the global CLI:
## `qmk cformat` ## `qmk cformat`
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. This command formats C code using clang-format.
**Usage**: 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>`
Run it with `-a` to format all core code, or pass filenames on the command line to run it on specific files.
**Usage for specified files**:
``` ```
qmk cformat [file1] [file2] [...] [fileN] qmk cformat [file1] [file2] [...] [fileN]
``` ```
**Usage for all core files**:
```
qmk cformat -a
```
**Usage for only changed files against origin/master**:
```
qmk cformat
```
**Usage for only changed files against branch_name**:
```
qmk cformat -b branch_name
```
## `qmk compile` ## `qmk compile`
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. 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.

View File

@ -1,16 +1,14 @@
"""Format C code according to QMK's style. """Format C code according to QMK's style.
""" """
import os
import subprocess import subprocess
from shutil import which from shutil import which
from milc import cli from milc import cli
import qmk.path
@cli.argument('files', nargs='*', arg_only=True, help='Filename(s) to format.') def cformat_run(files, all_files):
@cli.subcommand("Format C code according to QMK's style.") """Spawn clang-format subprocess with proper arguments
def cformat(cli):
"""Format C code according to QMK's style.
""" """
# Determine which version of clang-format to use # Determine which version of clang-format to use
clang_format = ['clang-format', '-i'] clang_format = ['clang-format', '-i']
@ -19,27 +17,48 @@ def cformat(cli):
if which(binary): if which(binary):
clang_format[0] = binary clang_format[0] = binary
break 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: 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.') cli.log.info('Successfully formatted the C code.')
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
cli.log.error('Error formatting C code!') cli.log.error('Error formatting C code!')
return False 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)

View File

@ -68,3 +68,17 @@ def normpath(path):
return Path(path) return Path(path)
return Path(os.environ['ORIG_CWD']) / 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

View File

@ -7,7 +7,8 @@ def check_subcommand(command, *args):
def test_cformat(): 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(): def test_compile():