Wie rufe ich das Clang-Format über einen CPP-Projektordner auf?


88

Gibt es eine Möglichkeit, so etwas wie clang-format --style=Webkiteinen gesamten cpp-Projektordner aufzurufen , anstatt ihn für jede Datei separat auszuführen?

Ich benutze clang-format.pyund vimmache das, aber ich gehe davon aus, dass es eine Möglichkeit gibt, dies einmal anzuwenden.

Antworten:


47

Wie wäre es mit:

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

im Projektordner. Die Option -i macht es an Ort und Stelle (standardmäßig wird die formatierte Ausgabe in stdout geschrieben).


1
oder wenn Sie eine Konfigurationsdatei verwenden und mehrere Dateitypen formatieren möchten: clang-format-3.6 -i -style=file *.cpp *.h *.hpp
mBardos

43
Leider wird dies nicht in Unterverzeichnisse zurückgeführt.
Antimon

4
Ja, * .cpp wird von der Shell erweitert. clang braucht nur eine Liste von Dateien. Erweiterte Optionen (wie rekursives Globbing) hängen von den Funktionen Ihrer Shell ab. Informationen zur Verwendung von **Konstrukten finden Sie unter unix.stackexchange.com/questions/49913/recursive-glob .
Sbarzowski

Was ist mit clang-tidy?
Aaron Franke

@AaronFranke Das *.cppGenerieren einer Liste von Dateien sollte funktionieren. Der clang-tidyBefehl ermöglicht die Übergabe mehrerer Dateien. `USAGE: clang-tidy [options] <source0> [... <sourceN>]` In der Praxis ist dies jedoch möglicherweise nicht der beste Weg. Clang-tidy führt eine viel tiefere Analyse durch, daher sind die Compiler-Flags für jede Datei usw. erforderlich. Wenn ich clang-tidy verwendete, hatte ich normalerweise eine "Kompilierungsdatenbank" - eine JSON-Datei mit den Befehlen für jede Datei und einem Skript, das ausgeführt wurde darüber. Es war vor ein paar Jahren, vielleicht gibt es jetzt einen besseren Weg.
Sbarzowski

88

Leider gibt es keine Möglichkeit, das Clang-Format rekursiv anzuwenden. *.cppstimmt nur mit Dateien im aktuellen Verzeichnis überein, nicht mit Unterverzeichnissen. Auch **/*funktioniert nicht.

Zum Glück gibt es eine Lösung: greift alle Dateinamen mit dem findBefehl und Rohr sie in zum Beispiel, wenn Sie alle formatieren möchten. .hUnd .cppDateien im Verzeichnis foo/bar/rekursiv, können Sie tun

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

Weitere Informationen finden Sie hier .


6
Nun, **/*.cppscheint in (einigermaßen moderner) Bash zu funktionieren. Möglicherweise müssen Sie shopt -s globstarvorher.
Sbarzowski

1
Wenn Sie CMake verwenden, zeigt Ihnen dieser Beitrag , wie Sie mit CMake GLOB_RECURSEalle .cppDateien finden und an diese übergeben können clang-format.
Phoenix

5
Die Kombination von findund xargssollte verwenden find ... -print0und xargs -0 ...sicherstellen, dass alle Arten von Dateinamen korrekt behandelt werden.
Alexander

4
Dieser Befehl schlägt fehl, wenn in pwd CPP- oder H-Dateien vorhanden sind. find foo/bar/ -iname '*.h' -o -iname '*.cpp' | xargs clang-format -iwird das Problem beheben.
Nyanpasu64

29

Erstellen Sie zuerst eine .clang-formatDatei, falls diese nicht vorhanden ist:

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

Wählen Sie den gewünschten vordefinierten Stil oder bearbeiten Sie die resultierende .clang-formatDatei.

Der Konfigurator im Clang-Format ist hilfreich.

Dann renne:

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

Andere Dateiendungen als cpp, hpp, ccund cxxkönnen im regulären Ausdruck verwendet werden, stellen Sie sicher , sie mit zu trennen \|.


Gibt -style=filees eine Möglichkeit, einen benutzerdefinierten Dateipfad anzugeben? Ich habe es versucht -style=~/.clang-formatund es funktioniert nicht.
Aaron Franke

Nicht das ich wüsste, abgesehen vom Ändern des aktuellen Verzeichnisses.
Alexander

Die Ghetto-Lösung, die ich mir ausgedacht habe, besteht darin, eine Funktion zu erstellen, die zuerst cp ~/.clang-format .den Befehl find in Ihrer Antwort ausführt.
Aaron Franke

12

Ich habe kürzlich ein Bash-Skript gefunden, das genau das tut, was Sie brauchen:

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

Dies ist ein Bash-Skript, das clang-format -iauf Ihrem Code ausgeführt wird.

Eigenschaften:

  • Findet den richtigen Pfad zu clang-formatUbuntu / Debian, das die LLVM-Version im clang-formatDateinamen codiert
  • Behebt Dateien rekursiv
  • Erkennt die am häufigsten von C / C ++ - Projekten verwendeten Dateierweiterungen

Unter Windows habe ich es erfolgreich in Git Bash und WSL verwendet.


3

Für Windows-Benutzer: Wenn Sie Powershell 3.0 unterstützen, können Sie Folgendes tun:

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

Hinweis 1: Verwenden Sie pushd .und, popdwenn Sie vor und nach dem Skript dasselbe aktuelle Verzeichnis haben möchten

Hinweis 2: Das Skript wird im aktuellen Arbeitsverzeichnis ausgeführt

Hinweis 3: Dies kann wahrscheinlich in einer einzigen Zeile geschrieben werden, wenn Ihnen das wirklich wichtig war


0

Ich verwende den folgenden Befehl, um alle Objective-C-Dateien unter dem aktuellen Ordner rekursiv zu formatieren :

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

Ich habe den folgenden Alias ​​in meinem definiert .bash_profile, um die Sache zu vereinfachen:

# 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"

0

Hier ist eine Lösung, die rekursiv sucht und alle Dateien in einem Befehl als Dateiliste in das Clang-Format weiterleitet. Es schließt auch das "build" -Verzeichnis aus (ich verwende CMake), aber Sie können einfach den "grep" -Schritt weglassen, um das zu entfernen.

shopt -s globstar extglob failglob && ls **/*.@(h|hpp|hxx|c|cpp|cxx) | grep -v build | tr '\n' ' ' | xargs clang-format -i

0

In der modernen Bash können Sie den Dateibaum rekursiv crawlen

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

Hier wird angenommen, dass sich die Quelle in befindet ./srcund .clang-formatdie Formatierungsinformationen enthält.


Ich glaube nicht, dass Globstar in Bash standardmäßig aktiviert ist, also müssten Sie es einstellen.
Eric Backus
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.