1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| import subprocess import sys from pathlib import Path from concurrent.futures import ThreadPoolExecutor, as_completed
EXTS = frozenset({'.c', '.cpp', '.cxx', '.h', '.hpp', '.hxx'})
ROOT = Path(__file__).resolve().parent
TARGET_DIRS = ('include/subdir1', 'src/subdir2')
EXCLUDE_DIRS = frozenset({'subdir3', 'subdir4'})
def main(argv=None): argv = argv if argv is not None else sys.argv CF_PATH = r"clang-format" clangformat = argv[1] if len(argv) > 1 else CF_PATH
try: subprocess.run([clangformat, '--version'], check=True) except (FileNotFoundError, subprocess.CalledProcessError): print(f"clang-format not found or failed at: {clangformat}") sys.exit(1)
files = [] for subdir in TARGET_DIRS: pdir = ROOT / subdir if not pdir.exists(): continue for p in pdir.rglob('*'): if any(part in EXCLUDE_DIRS for part in p.parts): continue if p.suffix.lower() in EXTS and p.is_file(): files.append(p)
def _format_one(p): try: proc = subprocess.run([clangformat, str(p)], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False) except FileNotFoundError: print(f"clang-format not found: {clangformat}") return False if proc.returncode != 0: err = proc.stderr.decode('utf-8', errors='replace').splitlines()[0] if proc.stderr else '' print(f"Error formatting {p}: {err}") return False formatted = proc.stdout
original = p.read_bytes() if formatted != original: p.write_bytes(formatted) print(f"Formatted: {p}") return True return False
count = 0 if files: with ThreadPoolExecutor() as ex: futures = {ex.submit(_format_one, p): p for p in files} for fut in as_completed(futures): try: if fut.result(): count += 1 except Exception as e: print(f"Exception formatting {futures[fut]}: {e}") print(f"[=OK=] Formatted {count} files.")
if __name__ == "__main__": main()
|