11import argparse
22import subprocess
33import sys
4- from collections .abc import Iterable
54from pathlib import Path
65
76from common import find_files
87
98
109class DefaultParameters :
1110 modified_files : bool = False
12- search_paths : Iterable [str ] = ["include" , "source " , "tests" ]
13- file_patterns : Iterable [str ] = ["*.cpp" , "*.hpp" , "*.c" , "*.h" ]
14- exclude_paths : Iterable [str ] = ["tests/external" ]
11+ search_paths : list [str ] = ["include" , "tests" ]
12+ file_patterns : list [str ] = ["*.cpp" , "*.hpp" , "*.c" , "*.h" ]
13+ exclude_paths : list [str ] = ["tests/external" ]
1514 check : bool = False
15+ clang_format_executable : str = "clang-format"
1616
1717
1818def parse_args ():
1919 parser = argparse .ArgumentParser ()
2020 parser .add_argument (
21- "-m" , "--modified-files" ,
22- type = bool ,
21+ "-m" ,
22+ "--modified-files" ,
2323 default = DefaultParameters .modified_files ,
2424 action = argparse .BooleanOptionalAction ,
25- help = "run clang-format only on the files modified since last pushed commit"
25+ help = "run clang-format only on the files modified since last pushed commit" ,
2626 )
2727 parser .add_argument (
28- "-p" , "--search-paths" ,
28+ "-p" ,
29+ "--search-paths" ,
2930 type = str ,
3031 default = DefaultParameters .search_paths ,
3132 nargs = "*" ,
32- action = "extend" ,
33- help = "list of search directory paths"
33+ help = "list of search directory paths" ,
3434 )
3535 parser .add_argument (
36- "-f" , "--file-patterns" ,
36+ "-f" ,
37+ "--file-patterns" ,
3738 type = str ,
3839 default = DefaultParameters .file_patterns ,
3940 nargs = "*" ,
40- action = "extend" ,
41- help = "list of file patterns to include"
41+ help = "list of file patterns to include" ,
4242 )
4343 parser .add_argument (
44- "-e" , "--exclude-paths" ,
44+ "-e" ,
45+ "--exclude-paths" ,
4546 type = str ,
4647 default = DefaultParameters .exclude_paths ,
4748 nargs = "*" ,
48- action = "extend" ,
49- help = "list of directory paths to exclude"
49+ help = "list of directory paths to exclude" ,
5050 )
5151 parser .add_argument (
52- "-c" , "--check" ,
53- type = bool ,
52+ "-c" ,
53+ "--check" ,
5454 default = DefaultParameters .check ,
5555 action = argparse .BooleanOptionalAction ,
56- help = "run format check"
56+ help = "run format check" ,
57+ )
58+ parser .add_argument (
59+ "-exe" ,
60+ "--clang-format-executable" ,
61+ type = str ,
62+ default = DefaultParameters .clang_format_executable ,
63+ help = "path or name of the clang-format executable (default: clang-format)" ,
5764 )
5865
5966 return vars (parser .parse_args ())
@@ -66,7 +73,7 @@ def get_modified_files(files: set[Path]) -> set[Path]:
6673 check = True ,
6774 stdout = subprocess .PIPE ,
6875 stderr = subprocess .PIPE ,
69- text = True
76+ text = True ,
7077 )
7178
7279 modified_files = {Path (file ) for file in result .stdout .splitlines () if file }
@@ -77,7 +84,7 @@ def get_modified_files(files: set[Path]) -> set[Path]:
7784 raise RuntimeError ("Failed to retrieve the modified files." )
7885
7986
80- def run_clang_format (files : set [Path ], check : bool ) -> int :
87+ def run_clang_format (clang_format_exec : str , files : set [Path ], check : bool ) -> int :
8188 n_files = len (files )
8289 if check :
8390 print (f"Files to check: { n_files } " )
@@ -88,32 +95,35 @@ def run_clang_format(files: set[Path], check: bool) -> int:
8895 for i , file in enumerate (files ):
8996 print (f"[{ i + 1 } /{ n_files } ] { file } " )
9097
91- cmd = ["clang-format-18" , str (file )]
98+ cmd = [clang_format_exec , str (file )]
9299 if check :
93100 cmd .extend (["--dry-run" , "--Werror" ])
94101 else :
95102 cmd .append ("-i" )
96103 result = subprocess .run (cmd , capture_output = True , text = True )
97104 if result .returncode != 0 :
98105 return_code = result .returncode
99- print (f"[Format error]\n [stdout]\n { result .stdout } \n [stderr]\n { result .stderr } " )
106+ print (
107+ f"[Format error]\n [stdout]\n { result .stdout } \n [stderr]\n { result .stderr } "
108+ )
100109
101110 print ("Done!" )
102111 return return_code
103112
104113
105114def main (
106115 modified_files : bool ,
107- search_paths : Iterable [str ],
108- file_patterns : Iterable [str ],
109- exclude_paths : Iterable [str ],
110- check : bool
116+ search_paths : list [str ],
117+ file_patterns : list [str ],
118+ exclude_paths : list [str ],
119+ check : bool ,
120+ clang_format_executable : str ,
111121):
112122 files_to_format = find_files (search_paths , file_patterns , exclude_paths )
113123 if modified_files :
114124 files_to_format = get_modified_files (files_to_format )
115125
116- sys .exit (run_clang_format (files_to_format , check ))
126+ sys .exit (run_clang_format (clang_format_executable , files_to_format , check ))
117127
118128
119129if __name__ == "__main__" :
0 commit comments