Как вызвать clang-формат над папкой проекта cpp?

87

Есть ли способ вызвать что-то вроде clang-format --style=Webkitдля всей папки проекта cpp, а не запускать ее отдельно для каждого файла?

Я использую clang-format.pyи vimдля этого, но полагаю, что есть способ применить это один раз.

user3639557
источник

Ответы:

46

Что о:

clang-format -i -style=WebKit *.cpp *.h

в папке проекта. Параметр -i делает его на месте (по умолчанию форматированный вывод записывается в стандартный вывод).

сбарзовский
источник
1
или если вы используете файл конфигурации и хотите отформатировать несколько типов файлов: clang-format-3.6 -i -style=file *.cpp *.h *.hpp
mBardos
41
К сожалению, это не рекурсивно в подкаталоги.
Antimony
4
Да, * .cpp будет расширен оболочкой. clang просто нужен список файлов. Более продвинутые параметры (например, рекурсивная подстановка) зависят от функций вашей оболочки. См. Unix.stackexchange.com/questions/49913/recursive-glob о том, как использовать **конструкцию.
sbarzowski
Что насчет с clang-tidy?
Аарон Франке,
@AaronFranke Использование *.cppдля создания списка файлов должно работать. Команда clang-tidyпозволяет передавать несколько файлов. `USAGE: clang-tidy [options] <source0> [... <sourceN>]` Однако на практике это может быть не лучшим способом. Clang-tidy выполняет гораздо более глубокий анализ, поэтому для него требуются флаги компилятора для каждого файла и т. Д. Когда я использовал clang-tidy, у меня обычно была «база данных компиляции» - файл JSON с командами для каждого файла и некоторый сценарий, который пошел над ним. Это было пару лет назад, может быть, есть способ получше.
sbarzowski
85

К сожалению, рекурсивно применить формат clang невозможно. *.cppбудет соответствовать только файлам в текущем каталоге, но не подкаталогам. Даже **/*не работает.

К счастью, есть решение: захватить с помощью findкоманды все имена файлов и передать их по конвейеру. Например, если вы хотите рекурсивно форматировать все файлы .hи .cppфайлы в каталоге foo/bar/, вы можете сделать

find foo/bar/ -iname *.h -o -iname *.cpp | xargs clang-format -i

См. Здесь для дополнительного обсуждения.

Сурьма
источник
6
Что ж, **/*.cppпохоже, работает в (достаточно современном) bash. Возможно, вам придется это сделать shopt -s globstarраньше.
sbarzowski
1
Если вы используете CMake, в этом посте показано, как с помощью CMake GLOB_RECURSEнайти все .cppфайлы и передать их clang-format.
феникс
4
Комбинация findи xargsдолжна использовать find ... -print0и xargs -0 ...для обеспечения правильной обработки всех типов имен файлов.
Александр
3
Эта команда не работает, если в pwd существуют файлы .cpp или .h. find foo/bar/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -iустранит проблему.
nyanpasu64
27

Сначала создайте .clang-formatфайл, если он не существует:

clang-format -style=WebKit -dump-config > .clang-format

Выберите любой предопределенный стиль или отредактируйте полученный .clang-formatфайл.

Конфигуратор clang-формата полезен.

Затем запустите:

find . -regex '.*\.\(cpp\|hpp\|cc\|cxx\)' -exec clang-format -style=file -i {} \;

Другие расширения файлов , чем cpp, hpp, ccи cxxможет быть использован в регулярном выражении, просто убедитесь , что отделить их \|.

Александр
источник
Ибо -style=fileесть ли способ указать собственный путь к файлу? Я попробовал, -style=~/.clang-formatно ничего не вышло.
Аарон Франке,
Не то, чтобы я знал, кроме изменения текущего каталога.
Александр
Решение для гетто, которое я придумал, - это создать функцию, которая сначала запускает cp ~/.clang-format .команду find в вашем ответе.
Аарон Франке,
12

Недавно я нашел bash-скрипт, который делает именно то, что вам нужно:

https://github.com/eklitzke/clang-format-all

Это сценарий bash, который будет запускаться clang-format -iв вашем коде.

Особенности:

  • Находит правильный путь к clang-formatUbuntu / Debian, который кодирует версию LLVM в имени clang-formatфайла
  • Рекурсивно исправляет файлы
  • Обнаруживает наиболее распространенные расширения файлов, используемые проектами C / C ++

В Windows я успешно использовал его в Git Bash и WSL.

Юлиус Буллингер
источник
3

Для пользователей Windows: если у вас есть поддержка Powershell 3.0, вы можете:

Get-ChildItem -Path . -Directory -Recurse |
    foreach {
        cd $_.FullName
        &clang-format -i -style=WebKit *.cpp
    }

Примечание 1: используйте pushd .и, popdесли вы хотите иметь один и тот же текущий каталог до и после скрипта.

Примечание 2: сценарий работает в текущем рабочем каталоге.

Примечание 3: это, вероятно, можно записать в одну строку, если это было действительно важно для вас

Тим Мейер
источник
0

Я использую следующую команду для рекурсивного форматирования всех файлов objective-C в текущей папке :

$ find . -name "*.m" -o -name "*.h" | sed 's| |\\ |g' | xargs clang-format -i

.bash_profileЧтобы упростить задачу, я определил в my следующий псевдоним :

# 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"
Marcelosalloum
источник
0

Вот решение, которое выполняет рекурсивный поиск и передает все файлы в формат 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
Бим
источник
0

В современном 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содержит информацию о форматировании.

Михаил
источник