Hoe roep ik clang-format aan over een cpp-projectmap?

Is er een manier om iets als clang-format --style=Webkitaan te roepen voor een hele cpp-projectmap, in plaats van het apart uit te voeren voor elk bestand?

Ik gebruik clang-format.pyen vimom dit te doen, maar ik neem aan dat er een manier is om dit eenmalig toe te passen.


Antwoord 1, autoriteit 100%

Helaas is er geen manier om clang-formaat recursief toe te passen. *.cppkomt alleen overeen met bestanden in de huidige map, niet met submappen. Zelfs **/*werkt niet.

Gelukkig is er een oplossing: pak alle bestandsnamen met de opdracht finden pijp ze erin. Als u bijvoorbeeld alle .hen .cppbestanden in de directory foo/bar/recursief, kunt u doen

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

Zie hiervoor aanvullende discussie.


Antwoord 2, autoriteit 52%

Hoe zit het met:

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

in de projectmap. De -i optie zorgt ervoor dat het op zijn plaats zit (standaard wordt geformatteerde uitvoer naar stdout geschreven).


Antwoord 3, autoriteit 33%

Maak eerst een .clang-formatbestand als het niet bestaat:

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

Kies de vooraf gedefinieerde stijl die je leuk vindt, of bewerk het resulterende bestand .clang-format.

clang-format configuratoris handig.

Voer vervolgens uit:

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

Andere bestandsextensies dan cpp, hpp, ccen cxxkunnen in de reguliere expressie worden gebruikt, zorg ervoor dat u ze scheidt met \|.


Antwoord 4, autoriteit 11%

Ik heb onlangs een bash-script gevonden dat precies doet wat je nodig hebt:

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

Dit is een bash-script dat clang-format -iop je code uitvoert.

Kenmerken:

  • Vindt het juiste pad naar clang-formatop Ubuntu/Debian, die de LLVM-versie codeert in de bestandsnaam clang-format
  • Repareert bestanden recursief
  • Detecteert de meest voorkomende bestandsextensies die worden gebruikt door C/C++-projecten

In Windows heb ik het met succes gebruikt in Git Bash en WSL.


Antwoord 5, autoriteit 7%

Voor de Windows-gebruikers: als je Powershell 3.0-ondersteuning hebt, kun je het volgende doen:

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

Opmerking1: Gebruik pushd .en popdals u dezelfde huidige map voor en na het script wilt hebben

Opmerking2: Het script werkt in de huidige werkmap

Opmerking 3: Dit kan waarschijnlijk in één regel worden geschreven als dat echt belangrijk voor je was


Antwoord 6, autoriteit 7%

Als je Windows (CMD) gebruikt maar het PowerShell-kanon niet wilt gebruiken om deze vlieg af te schieten, probeer dan dit:

for /r %t in (*.cpp *.h) do clang-format -i -style=WebKit "%t"

Vergeet niet om de twee %s te dupliceren als in een cmd-script.


Antwoord 7, autoriteit 3%

Het onderstaande script en proces:

  1. werkt in Linux
  2. zou moeten werken op MacOS
  3. werkt in Windowsbinnen Git For Windowsterminal met clang-formatgedownload en geïnstalleerd.

Zo doe ik het:

Ik maak een run_clang_format.sh-script en plaats het in de hoofdmap van mijn projectdirectory, dan voer ik het overal uit. Zo ziet het eruit:

run_clang_format.sh

#!/bin/bash
THIS_PATH="$(realpath "$0")"
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

Het gebruik van --style=filebetekent dat ik ook een aangepast .clang-formatclang-format specificatiebestand op hetzelfde niveau moet hebben, wat ik doe.

Maak nu uw nieuw gemaakte run_clang_format.sh-bestand uitvoerbaar:

chmod +x run_clang_format.sh

…en voer het uit:

./run_clang_format.sh

Hier is een voorbeeldrun en uitvoer voor mij:

~/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

Je kunt mijn run_clang_format.sh-bestand in mijn eRCaGuy_PPM_Writer-repository en in mijn eRCaGuy_CodeFormatterrepository ook. Mijn .clang-format-bestand is er ook.

Referenties:

  1. Mijn opslagplaats:
    1. eRCaGuy_PPM_Writerrepo
    2. run_clang_format.shbestand
  2. Mijn opmerkingen over het gebruik van clang-formatin mijn “git & Linux cmds, help, tips & tricks – Gabriel.txt”document in mijn eRCaGuy_dotfilesrepo (zoek het document op “clang-format”).
  3. Officiële clang-formatdocumentatie, setup, instructies, etc! https://clang.llvm.org/docs/ClangFormat.html
  4. Download het clang-formatauto-formatter/linter uitvoerbaar bestand voor Windows, of andere installatieprogramma’s/uitvoerbare bestanden hier: https://llvm.org/builds/
  5. Clang-Format-stijlopties: https://clang.llvm.org/docs/ClangFormatStyleOptions .html
  6. [mijn antwoord] Hoe kan ik de brondirectory van een Bash-script uit het script zelf halen?

Gerelateerd:

  1. [mijn antwoord] Preprocessor-richtlijnen inspringen met clang-formaat

Zie ook:

  1. [mijn antwoord] https://stackoverflow .com/questions/67678531/fixing-a-simple-c-code-without-the-coments/67678570#67678570

Antwoord 8

Ik gebruik de volgende opdracht om alle objective-C-bestanden onder de huidige map recursiefop te maken:

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

Ik heb de volgende alias gedefinieerd in mijn .bash_profileom dingen gemakkelijker te maken:

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

Antwoord 9

Hier is een oplossing die recursief zoekt en alle bestanden in één commando naar clang-formaat stuurt als een bestandslijst. Het sluit ook de map “build” uit (ik gebruik CMake), maar je kunt de stap “grep” gewoon weglaten om die te verwijderen.

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

Antwoord 10

In moderne bash kun je recursief de bestandsstructuur 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 wordt aangenomen dat de bron zich in ./srcbevindt en het .clang-formatbevat de opmaakinformatie.


Antwoord 11

Zoals @sbarzowski in een opmerking hierboven aangeeft, kun je in bash globstarwaardoor **recursief uitbreidt.

Als je het alleen voor deze ene opdracht wilt, kun je zoiets als het volgende doen om alle .h, .ccen .cppbestanden.

(shopt -s globstar; clang-format -i **/*.{h,cc,cpp})

Of je kunt shopt -s globstartoevoegen aan je .bashrcen de hele tijd **goedheid hebben in bash.

Als een kanttekening, wil je misschien de eerste keer --dry-runmet clang-formaat gebruiken om er zeker van te zijn dat het is wat je wilt.


Antwoord 12

U kunt dit gebruiken in een Make-bestand. Het gebruikt git ls-files --exclude-standardom de lijst met bestanden te krijgen, dus dat betekent dat niet-getrackte bestanden automatisch worden overgeslagen. Het gaat ervan uit dat je een .clang-tidy-bestand in de hoofdmap van je project hebt.

format:
ifeq ($(OS), Windows_NT)
    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
endif

Uitvoeren met make format

Merk op dat ik ontsnapt ben aan $met $$voor make.

Als je go-task gebruikt in plaats van make, heb je dit nodig:

 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}}

Uitvoeren met task format

Als je de afzonderlijke scripts wilt uitvoeren, gebruik dan deze

# 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

Other episodes