如何通过 cpp 项目文件夹调用 clang-format?
How to call clang-format over a cpp project folder?
有没有办法为整个 cpp 项目文件夹调用类似 clang-format --style=Webkit
的方法,而不是为每个文件分别调用 运行 ?
我正在使用 clang-format.py
和 vim
来执行此操作,但我认为有一种方法可以应用一次。
怎么样:
clang-format -i -style=WebKit *.cpp *.h
在项目文件夹中。 -i 选项使其就位(默认情况下,格式化输出写入标准输出)。
不幸的是,没有办法递归地应用 clang-format。 *.cpp
只会匹配当前目录下的文件,不会匹配子目录下的文件。即使 **/*
也不起作用。
幸运的是,有一个解决方案:使用 find
命令获取所有文件名并将它们通过管道输入。例如,如果你想格式化所有 .h
和 .cpp
递归目录 foo/bar/
中的文件,你可以做
find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i
有关其他讨论,请参阅 here。
我最近发现了一个 bash-脚本,它可以满足您的需求:
https://github.com/eklitzke/clang-format-all
This is a bash script that will run clang-format -i
on your code.
Features:
- Finds the right path to
clang-format
on Ubuntu/Debian, which encode the LLVM version in the clang-format
filename
- Fixes files recursively
- Detects the most common file extensions used by C/C++ projects
在Windows上,我在GitBash和WSL中使用成功
先创建一个.clang-format
文件,如果不存在:
clang-format -style=WebKit -dump-config > .clang-format
选择您喜欢的预定义样式,或编辑生成的 .clang-format
文件。
clang-format configurator 很有帮助。
然后 运行:
find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;
除cpp
、hpp
、cc
和cxx
之外的其他文件扩展名都可以在正则表达式中使用,只要确保用[=18分隔即可=].
对于 Windows 用户:如果您有 Powershell 3.0 支持,您可以:
Get-ChildItem -Path . -Directory -Recurse |
foreach {
cd $_.FullName
&clang-format -i -style=WebKit *.cpp
}
注意1:如果你想在脚本前后有相同的当前目录,请使用pushd .
和popd
注2:脚本运行在当前工作目录
注3:如果这对你来说真的很重要,这可能可以写成一行
我正在使用以下命令以递归方式格式化当前文件夹下的所有 objective-C 文件:
$ find . -name "*.m" -o -name "*.h" | sed 's| |\ |g' | xargs clang-format -i
我在 .bash_profile
中定义了以下别名以简化操作:
# Format objC files (*.h and *.m) under the current folder, recursively
alias clang-format-all="find . -name \"*.m\" -o -name \"*.h\" | sed 's| |\ |g' | xargs clang-format -i"
这是一个递归搜索的解决方案,并在一个命令中将所有文件通过管道传输为 clang 格式作为文件列表。它还排除了 "build" 目录(我使用 CMake),但您可以省略 "grep" 步骤来删除它。
shopt -s globstar extglob failglob && ls **/*.@(h|hpp|hxx|c|cpp|cxx) | grep -v build | tr '\n' ' ' | xargs clang-format -i
现代bash你可以递归抓取文件树
for file_name in ./src/**/*.{cpp,h,hpp}; do
if [ -f "$file_name" ]; then
printf '%s\n' "$file_name"
clang-format -i $file_name
fi
done
此处假定源位于 ./src
并且 .clang-format
包含格式信息。
当您使用 Windows (CMD) 但不想使用 PowerShell 大炮来射击这只苍蝇时,试试这个:
for /r %t in (*.cpp *.h) do clang-format -i -style=WebKit "%t"
如果在 cmd 脚本中,请不要忘记复制这两个 %
。
下面的脚本和过程:
- 在Linux
工作
- 应该适用于 MacOS
- 在 Windows 中工作 Git For Windows terminal with
clang-format
downloaded and installed。
这是我的做法:
我创建了一个 run_clang_format.sh
脚本并将其放在我的项目目录的根目录中,然后我从任何地方 运行 它。这是它的样子:
#!/bin/bash
THIS_PATH="$(realpath "[=10=]")"
THIS_DIR="$(dirname "$THIS_PATH")"
# Find all files in THIS_DIR which end in .ino, .cpp, etc., as specified
# in the regular expression just below
FILE_LIST="$(find "$THIS_DIR" | grep -E ".*(\.ino|\.cpp|\.c|\.h|\.hpp|\.hh)$")"
echo -e "Files found to format = \n\"\"\"\n$FILE_LIST\n\"\"\""
# Format each file.
# - NB: do NOT put quotes around `$FILE_LIST` below or else the `clang-format` command will
# mistakenly see the entire blob of newline-separated file names as a SINGLE file name instead
# of as a new-line separated list of *many* file names!
clang-format --verbose -i --style=file $FILE_LIST
使用 --style=file
意味着我还必须在同一级别有一个自定义的 .clang-format
clang 格式说明符文件,我就是这样做的。
现在,使您新创建的 run_clang_format.sh
文件可执行:
chmod +x run_clang_format.sh
...和运行它:
./run_clang_format.sh
这是一个示例 运行 并为我输出:
~/GS/dev/eRCaGuy_PPM_Writer$ ./run_clang-format.sh
Files found to format =
"""
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
"""
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
你可以找到我的 run_clang_format.sh
file in my eRCaGuy_PPM_Writer repository, and in my eRCaGuy_CodeFormatter repository too. My .clang-format
file is there too.
参考文献:
- 我的仓库:
- 我关于如何在我的 "git & Linux cmds, help, tips & tricks - Gabriel.txt" doc in my eRCaGuy_dotfiles 存储库中使用
clang-format
的笔记(在文档中搜索“clang-format”)。
- 官方
clang-format
文档、设置、说明等! https://clang.llvm.org/docs/ClangFormat.html
- 在此处下载
clang-format
auto-formatter/linter Windows 或其他 installers/executables 的可执行文件:https://llvm.org/builds/
- Clang 格式样式选项:https://clang.llvm.org/docs/ClangFormatStyleOptions.html
- [我的回答]How can I get the source directory of a Bash script from within the script itself?
相关:
- [我的回答]Indenting preprocessor directives with clang-format
另请参阅:
- [我的回答]
正如@sbarzowski 在上面的评论中提到的那样,在 bash 中,您可以启用 globstar,这会导致 **
递归扩展。
如果您只需要它用于这一个命令,您可以执行类似以下的操作来格式化所有 .h
、.cc
和 .cpp
文件。
(shopt -s globstar; clang-format -i **/*.{h,cc,cpp})
或者您可以将 shopt -s globstar
添加到您的 .bashrc
并在 bash 中始终拥有 **
善良。
作为旁注,您可能希望第一次使用 --dry-run
和 clang-format 以确保它是您想要的。
您可以在 Make 文件中使用它。它使用 git ls-files --exclude-standard
来获取文件列表,这意味着自动跳过未跟踪的文件。它假定您的项目根目录下有一个 .clang-tidy
文件。
format:
ifeq ($(OS), Windows_NT)
pwsh -c '$$files=(git ls-files --exclude-standard); foreach ($$file in $$files) { if ((get-item $$file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $$file } }'
else
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$$' | xargs clang-format -i -style=file
endif
运行 与 make format
请注意,我使用 $$
对 make 进行了转义 $
。
如果您使用 go-task 而不是 make,您将需要:
format:
- |
{{if eq OS "windows"}}
powershell -c '$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }'
{{else}}
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file
{{end}}
运行 与 task format
如果你想运行单独的脚本,那么使用这些
# powershell
$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }
# bash
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file
有没有办法为整个 cpp 项目文件夹调用类似 clang-format --style=Webkit
的方法,而不是为每个文件分别调用 运行 ?
我正在使用 clang-format.py
和 vim
来执行此操作,但我认为有一种方法可以应用一次。
怎么样:
clang-format -i -style=WebKit *.cpp *.h
在项目文件夹中。 -i 选项使其就位(默认情况下,格式化输出写入标准输出)。
不幸的是,没有办法递归地应用 clang-format。 *.cpp
只会匹配当前目录下的文件,不会匹配子目录下的文件。即使 **/*
也不起作用。
幸运的是,有一个解决方案:使用 find
命令获取所有文件名并将它们通过管道输入。例如,如果你想格式化所有 .h
和 .cpp
递归目录 foo/bar/
中的文件,你可以做
find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i
有关其他讨论,请参阅 here。
我最近发现了一个 bash-脚本,它可以满足您的需求:
https://github.com/eklitzke/clang-format-all
This is a bash script that will run
clang-format -i
on your code.Features:
- Finds the right path to
clang-format
on Ubuntu/Debian, which encode the LLVM version in theclang-format
filename- Fixes files recursively
- Detects the most common file extensions used by C/C++ projects
在Windows上,我在GitBash和WSL中使用成功
先创建一个.clang-format
文件,如果不存在:
clang-format -style=WebKit -dump-config > .clang-format
选择您喜欢的预定义样式,或编辑生成的 .clang-format
文件。
clang-format configurator 很有帮助。
然后 运行:
find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;
除cpp
、hpp
、cc
和cxx
之外的其他文件扩展名都可以在正则表达式中使用,只要确保用[=18分隔即可=].
对于 Windows 用户:如果您有 Powershell 3.0 支持,您可以:
Get-ChildItem -Path . -Directory -Recurse |
foreach {
cd $_.FullName
&clang-format -i -style=WebKit *.cpp
}
注意1:如果你想在脚本前后有相同的当前目录,请使用pushd .
和popd
注2:脚本运行在当前工作目录
注3:如果这对你来说真的很重要,这可能可以写成一行
我正在使用以下命令以递归方式格式化当前文件夹下的所有 objective-C 文件:
$ find . -name "*.m" -o -name "*.h" | sed 's| |\ |g' | xargs clang-format -i
我在 .bash_profile
中定义了以下别名以简化操作:
# Format objC files (*.h and *.m) under the current folder, recursively
alias clang-format-all="find . -name \"*.m\" -o -name \"*.h\" | sed 's| |\ |g' | xargs clang-format -i"
这是一个递归搜索的解决方案,并在一个命令中将所有文件通过管道传输为 clang 格式作为文件列表。它还排除了 "build" 目录(我使用 CMake),但您可以省略 "grep" 步骤来删除它。
shopt -s globstar extglob failglob && ls **/*.@(h|hpp|hxx|c|cpp|cxx) | grep -v build | tr '\n' ' ' | xargs clang-format -i
现代bash你可以递归抓取文件树
for file_name in ./src/**/*.{cpp,h,hpp}; do
if [ -f "$file_name" ]; then
printf '%s\n' "$file_name"
clang-format -i $file_name
fi
done
此处假定源位于 ./src
并且 .clang-format
包含格式信息。
当您使用 Windows (CMD) 但不想使用 PowerShell 大炮来射击这只苍蝇时,试试这个:
for /r %t in (*.cpp *.h) do clang-format -i -style=WebKit "%t"
如果在 cmd 脚本中,请不要忘记复制这两个 %
。
下面的脚本和过程:
- 在Linux 工作
- 应该适用于 MacOS
- 在 Windows 中工作 Git For Windows terminal with
clang-format
downloaded and installed。
这是我的做法:
我创建了一个 run_clang_format.sh
脚本并将其放在我的项目目录的根目录中,然后我从任何地方 运行 它。这是它的样子:
#!/bin/bash
THIS_PATH="$(realpath "[=10=]")"
THIS_DIR="$(dirname "$THIS_PATH")"
# Find all files in THIS_DIR which end in .ino, .cpp, etc., as specified
# in the regular expression just below
FILE_LIST="$(find "$THIS_DIR" | grep -E ".*(\.ino|\.cpp|\.c|\.h|\.hpp|\.hh)$")"
echo -e "Files found to format = \n\"\"\"\n$FILE_LIST\n\"\"\""
# Format each file.
# - NB: do NOT put quotes around `$FILE_LIST` below or else the `clang-format` command will
# mistakenly see the entire blob of newline-separated file names as a SINGLE file name instead
# of as a new-line separated list of *many* file names!
clang-format --verbose -i --style=file $FILE_LIST
使用 --style=file
意味着我还必须在同一级别有一个自定义的 .clang-format
clang 格式说明符文件,我就是这样做的。
现在,使您新创建的 run_clang_format.sh
文件可执行:
chmod +x run_clang_format.sh
...和运行它:
./run_clang_format.sh
这是一个示例 运行 并为我输出:
~/GS/dev/eRCaGuy_PPM_Writer$ ./run_clang-format.sh
Files found to format =
"""
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
/home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
"""
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo/PPM_Writer_demo.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/examples/PPM_Writer_demo2/PPM_Writer_demo2.ino
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.h
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/eRCaGuy_PPM_Writer.cpp
Formatting /home/gabriel/GS/dev/eRCaGuy_PPM_Writer/src/timers/eRCaGuy_TimerCounterTimers.h
你可以找到我的 run_clang_format.sh
file in my eRCaGuy_PPM_Writer repository, and in my eRCaGuy_CodeFormatter repository too. My .clang-format
file is there too.
参考文献:
- 我的仓库:
- 我关于如何在我的 "git & Linux cmds, help, tips & tricks - Gabriel.txt" doc in my eRCaGuy_dotfiles 存储库中使用
clang-format
的笔记(在文档中搜索“clang-format”)。 - 官方
clang-format
文档、设置、说明等! https://clang.llvm.org/docs/ClangFormat.html - 在此处下载
clang-format
auto-formatter/linter Windows 或其他 installers/executables 的可执行文件:https://llvm.org/builds/ - Clang 格式样式选项:https://clang.llvm.org/docs/ClangFormatStyleOptions.html
- [我的回答]How can I get the source directory of a Bash script from within the script itself?
相关:
- [我的回答]Indenting preprocessor directives with clang-format
另请参阅:
- [我的回答]
正如@sbarzowski 在上面的评论中提到的那样,在 bash 中,您可以启用 globstar,这会导致 **
递归扩展。
如果您只需要它用于这一个命令,您可以执行类似以下的操作来格式化所有 .h
、.cc
和 .cpp
文件。
(shopt -s globstar; clang-format -i **/*.{h,cc,cpp})
或者您可以将 shopt -s globstar
添加到您的 .bashrc
并在 bash 中始终拥有 **
善良。
作为旁注,您可能希望第一次使用 --dry-run
和 clang-format 以确保它是您想要的。
您可以在 Make 文件中使用它。它使用 git ls-files --exclude-standard
来获取文件列表,这意味着自动跳过未跟踪的文件。它假定您的项目根目录下有一个 .clang-tidy
文件。
format:
ifeq ($(OS), Windows_NT)
pwsh -c '$$files=(git ls-files --exclude-standard); foreach ($$file in $$files) { if ((get-item $$file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $$file } }'
else
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$$' | xargs clang-format -i -style=file
endif
运行 与 make format
请注意,我使用 $$
对 make 进行了转义 $
。
如果您使用 go-task 而不是 make,您将需要:
format:
- |
{{if eq OS "windows"}}
powershell -c '$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }'
{{else}}
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file
{{end}}
运行 与 task format
如果你想运行单独的脚本,那么使用这些
# powershell
$files=(git ls-files --exclude-standard); foreach ($file in $files) { if ((get-item $file).Extension -in ".cpp", ".hpp", ".c", ".cc", ".cxx", ".hxx", ".ixx") { clang-format -i -style=file $file } }
# bash
git ls-files --exclude-standard | grep -E '\.(cpp|hpp|c|cc|cxx|hxx|ixx)$' | xargs clang-format -i -style=file