-
Notifications
You must be signed in to change notification settings - Fork 141
Source formatting
This page gives some hints about installing clang-format and how to use it on its own, integrated with vim/emacs, or with git.
Remember, clang-format can be selectively disabled for certain chunks of code (e.g. nicely formatted matrix literals, etc.) with
// clang-format off
Matrix my_matrix = { {1, 2, 3},
{4, 5, 6},
{7, 8 ,9} };
// clang-format on
Of course, this should be used as sparingly as possible.
clang-format is available on Mac OSX in both macports and homebrew.
Configure apt to pull directly from apt.llvm.org's package index:
Add the archive signature (same signature for all versions):
$ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
For example, for llvm 7.0 on Ubuntu 18.04
$ echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main" >
/etc/apt/sources.list.d/llvm.list
$ echo "deb-src http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main" >
/etc/apt/sources.list.d/llvm.list
Now install using apt:
$ apt update
$ apt install clang-format-7
Install the pre-build binaries on almost any ubuntu-based distro:
wget http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz
tar xvJf ./clang+llvm-7.0.0*
cp clang+llvm-7.0.0*/bin/clang-format </somewhere/in/your/PATH>
This is likely the easiest and safest way to use clang-format if you aren't using it within your editor as you are writing the code itself.
This pre-commit hook will run any time git commit
is executed. It will check
the files to be committed, and if there are formatting errors, it will show the
diff, and ask the user if they wish to format them or abort.
Be sure to check the diff and ensure that the formatting is what you want.
Add the following to local_git_repo/.git/hooks/pre-commit
#!/bin/bash
# git pre-commit hook that checks the to-be-committed files, and offers to
# format them if necesssary
#
# M. Graham Lopez (2018)
echo "pre-commit hook checking code formatting"
clean=0
# the list of files to be committed
for bob in $(git diff --cached --name-status | awk '$1 != "D" { print $2 }' | grep '\.cpp$\|\.hpp$') ; do
diff -u --color ${bob} <(clang-format ${bob})
if [[ $? != 0 ]] ; then clean=1 ; fi # save if we saw a difference
done
if [[ $clean == 1 ]] ; then
echo ""
echo "There are un-formatted changes being commited"
echo "Choose to (C)ommit anyway, (F)ormat all and commit, (A)bort the commit"
exec < /dev/tty
PS3="Select: "
select yn in "Commit" "Format" "Abort"; do
casevar=${yn:-$REPLY}
case $casevar in
1|Commit|C|c)
echo "okay, continuing with commit anyway"
exit 0
break
;;
2|Format|F|f)
echo "formatting"
for bob in $(git diff --cached --name-status | awk '$1 != "D" { print $2 }') ; do
clang-format -i ${bob}
git add ${bob}
done
exit 0
;;
3|Abort|A|a)
echo "exiting"
exit 1
;;
esac
done
else # there were no differences
exit 0
fi
Add the git integration file somewhere in your path
The workflow to format your changed code:
- Make codes changes in your working copy.
- Run
git add your_changed_file.cpp
- Run
git clang-format --extensions cpp,hpp
, and you will probably see modifications inyour_changed_file.cpp
, these modifications are generated from clang-format. - Run
git add your_changed_file.cpp
, and commit your change. Now the branch is ready to be opened as a pull request.
If you want to format the changed code on your latest git commit (HEAD), you can
run git clang-format --extensions cpp,hpp HEAD~1
. See git clang-format -h
for more details.
-
clang-format <file(s)>
will print to stdout the formatted file(s) -
clang-format -i <file(s)>
will format (edit) the file(s) in place -
diff -u --color file.cpp <(clang-format file.cpp)
to see the potential changes (may not work in a script) -
clang-format file.cpp | diff file.cpp -
(alternate) to see the potential changes
- find the clang-format.py that came with your clang-format installtion. In the
LLVM install tree, it is at
share/clang/clang-format.py
or grab the latest one here. It is not version dependent. - add this file to your path. It allows vim to interface with whichever clang-format shows up first in the user's path.
The following in your .vimrc
will cause "ctrl+f" to apply the clang-format
style to the current line in normal or insert mode, or a visual selection (use
shift+v
+ movement in normal mode to make selection):
if has('python3')
noremap <C-f> :py3f /usr/local/bin/clang-format.py<cr>
inoremap <C-f> :py3f /usr/local/bin/clang-format.py<cr>
endif
This will make changes without the ability to verify them first. use caution
Add something like the following to your .vimrc
:
function! Formatonsave()
let l:formatdiff = 1
pyf ~/llvm/tools/clang/tools/clang-format/clang-format.py
endfunction
autocmd BufWritePre *.h,*.cc,*.cpp call Formatonsave()
Two basic routes are available here:
-
One is the install the clang-format.el using your favored package manager for emacs {MELPA, el-get}
-
The other is to just pull the clang-format.el from the clang-format source. It is here in the canonical llvm github mirror: https://github.com/llvm/llvm-project/blob/master/clang/tools/clang-format/clang-format.el In your cloned llvm repo it will be at the same relative location.
Then add this to your .emacs
(load "<path-to-clang>/tools/clang-format/clang-format.el") ;;not needed with el-get
(global-set-key [C-M-tab] 'clang-format-region)
This c-style definition closely approximates our clang-format spec for real time formatting.
This spacemacs clang-format integration looks like a promising approach to get the auto-format on save functionality that the vim integration has. We are in search of a similar code snippet for gnu-emacs.