aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2020-01-13 07:48:49 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2020-01-13 08:01:21 +0300
commit585aeabfd21d1f678f80e3782b3fd3c29c469320 (patch)
tree73113ba05d8540979f2d3594caf1df93663a5be6 /tools
parentAppVeyor: fast_finish (diff)
downloadcmake-common-585aeabfd21d1f678f80e3782b3fd3c29c469320.tar.gz
cmake-common-585aeabfd21d1f678f80e3782b3fd3c29c469320.zip
add clang-format.sh
This allows to call clang-format in either the in-place editing mode (default), or the diff mode (`--diff`, will only print the unified diff between the formatted and the original files.
Diffstat (limited to 'tools')
-rw-r--r--tools/clang-format/.gitattributes1
-rwxr-xr-xtools/clang-format/clang-format.sh186
2 files changed, 187 insertions, 0 deletions
diff --git a/tools/clang-format/.gitattributes b/tools/clang-format/.gitattributes
new file mode 100644
index 0000000..dfdb8b7
--- /dev/null
+++ b/tools/clang-format/.gitattributes
@@ -0,0 +1 @@
+*.sh text eol=lf
diff --git a/tools/clang-format/clang-format.sh b/tools/clang-format/clang-format.sh
new file mode 100755
index 0000000..00fe712
--- /dev/null
+++ b/tools/clang-format/clang-format.sh
@@ -0,0 +1,186 @@
+#!/usr/bin/env bash
+
+# Copyright (c) 2020 Egor Tensin <Egor.Tensin@gmail.com>
+# This file is part of the "cmake-common" project.
+# For details, see https://github.com/egor-tensin/cmake-common.
+# Distributed under the MIT License.
+
+set -o errexit -o nounset -o pipefail
+
+# Utility
+
+script_name="$( basename -- "${BASH_SOURCE[0]}" )"
+readonly script_name
+
+dump() {
+ local prefix="${FUNCNAME[0]}"
+ [ "${#FUNCNAME[@]}" -gt 1 ] && prefix="${FUNCNAME[1]}"
+
+ local msg
+ for msg; do
+ echo "$script_name: $prefix: $msg"
+ done
+}
+
+# Settings
+
+clang_format='clang-format'
+clang_format_style='file'
+clang_format_diff=
+
+update_clang_format() {
+ if [ "$#" -ne 1 ]; then
+ echo "usage: ${FUNCNAME[0]} CLANG_FORMAT_PATH" >&2
+ return 1
+ fi
+
+ local new_clang_format="$1"
+
+ if ! command -v "$new_clang_format" > /dev/null 2>&1; then
+ dump "couldn't find clang-format at: $new_clang_format" >&2
+ return 1
+ fi
+
+ clang_format="$new_clang_format"
+}
+
+# Command line parsing
+
+script_usage() {
+ local msg
+ for msg; do
+ echo "$script_name: $msg"
+ done
+
+ echo "usage: $script_name [-h|--help] [-b|--clang-format PATH] [-s|--style STYLE] [--diff]
+ -h,--help show this message and exit
+ -b,--clang-format set path to clang-format executable
+ -s,--style clang-format -style parameter argument
+ --diff don't edit the files, just show the diff"
+}
+
+parse_script_options() {
+ while [ "$#" -gt 0 ]; do
+ local key="$1"
+ shift
+
+ case "$key" in
+ -h|--help)
+ script_usage
+ exit 0
+ ;;
+ --diff)
+ clang_format_diff=1
+ continue
+ ;;
+ -b|--clang-format|-s|--style)
+ ;;
+ *)
+ script_usage "unrecognized parameter: $key" >&2
+ exit 1
+ ;;
+ esac
+
+ if [ "$#" -eq 0 ]; then
+ script_usage "missing argument for parameter: $key" >&2
+ exit 1
+ fi
+
+ local value="$1"
+ shift
+
+ case "$key" in
+ -b|--clang-format)
+ update_clang_format "$value"
+ ;;
+ -s|--style)
+ clang_format_style="$value"
+ ;;
+ *)
+ script_usage "unrecognized parameter: $key" >&2
+ exit 1
+ ;;
+ esac
+ done
+}
+
+# Routines for running clang-format
+
+run_clang_format_diff() {
+ local exit_code=0
+ local file
+
+ for file; do
+ if "$clang_format" "-style=$clang_format_style" -- "$file" | diff --unified --label="$file (original)" --label="$file (clang-format)" -- "$file" -; then
+ continue
+ else
+ exit_code="$?"
+ [ "$exit_code" -eq 1 ] && continue
+ break
+ fi
+ done
+
+ return "$exit_code"
+}
+
+run_clang_format_edit() {
+ "$clang_format" -i "-style=$clang_format_style" -- "$@"
+}
+
+run_clang_format() {
+ if [ -z "$clang_format_diff" ]; then
+ run_clang_format_edit "$@"
+ else
+ run_clang_format_diff "$@"
+ fi
+}
+
+# File traversal
+
+list_all_files() {
+ git ls-tree -r -z --name-only HEAD
+}
+
+declare -a cpp_extensions=(c h cc hh cpp hpp cxx hxx cp c++)
+
+list_cpp_files() {
+ local -A cpp_extension_set
+ local ext
+
+ for ext in ${cpp_extensions[@]+"${cpp_extensions[@]}"}; do
+ cpp_extension_set[$ext]=1
+ done
+
+ local -a files=()
+ local file
+
+ while IFS= read -d '' -r file; do
+ basename="$( basename -- "$file" )"
+ ext="${basename##*.}"
+ [ "$ext" = "$basename" ] && continue # No .EXTension
+
+ [ -n "${cpp_extension_set[$ext]+x}" ] && files+=("$file")
+ done < <( list_all_files )
+
+ printf -- '%s\0' ${files[@]+"${files[@]}"}
+}
+
+# Main routines
+
+process_cpp_files() {
+ local -a files=()
+ local file
+
+ while IFS= read -d '' -r file; do
+ files+=("$file")
+ done < <( list_cpp_files )
+
+ run_clang_format ${files[@]+"${files[@]}"}
+}
+
+main() {
+ parse_script_options "$@"
+ process_cpp_files
+}
+
+main "$@"