.run-format.zsh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/usr/bin/env zsh
  2. builtin emulate -L zsh
  3. setopt EXTENDED_GLOB
  4. setopt PUSHD_SILENT
  5. setopt ERR_EXIT
  6. setopt ERR_RETURN
  7. setopt NO_UNSET
  8. setopt PIPE_FAIL
  9. setopt NO_AUTO_PUSHD
  10. setopt NO_PUSHD_IGNORE_DUPS
  11. setopt FUNCTION_ARGZERO
  12. ## Enable for script debugging
  13. # setopt WARN_CREATE_GLOBAL
  14. # setopt WARN_NESTED_VAR
  15. # setopt XTRACE
  16. autoload -Uz is-at-least && if ! is-at-least 5.2; then
  17. print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade zsh to fix this issue."
  18. exit 1
  19. fi
  20. invoke_formatter() {
  21. if (( # < 1 )) {
  22. log_error "Usage invoke_formatter [formatter_name]"
  23. exit 2
  24. }
  25. case ${1} {
  26. clang)
  27. if (( ${+commands[clang-format-16]} )) {
  28. local formatter=clang-format-16
  29. } elif (( ${+commands[clang-format]} )) {
  30. local formatter=clang-format
  31. local -a formatter_version=($(clang-format --version))
  32. if ! is-at-least 16.0.5 ${formatter_version[-1]}; then
  33. log_error "clang-format is not version 16.0.5 or above (found ${formatter_version[-1]}."
  34. exit 2
  35. fi
  36. if ! is-at-least ${formatter_version[-1]} 16.0.5; then
  37. log_error "clang-format is more recent than version 16.0.5 (found ${formatter_version[-1]})."
  38. exit 2
  39. fi
  40. } else {
  41. log_error "No viable clang-format version found (required 16.0.5)"
  42. exit 2
  43. }
  44. local -a source_files=(src/**/*.(c|cpp|h|hpp|m|mm)(.N))
  45. local -a format_args=(-style=file -fallback-style=none)
  46. if (( _loglevel > 2 )) format_args+=(--verbose)
  47. ;;
  48. cmake)
  49. local formatter=cmake-format
  50. if (( ${+commands[cmake-format]} )) {
  51. local cmake_format_version=$(cmake-format --version)
  52. if ! is-at-least 0.6.13 ${cmake_format_version}; then
  53. log_error "cmake-format is not version 0.6.13 or above (found ${cmake_format_version})."
  54. exit 2
  55. fi
  56. } else {
  57. log_error "No viable cmake-format version found (required 0.6.13)"
  58. exit 2
  59. }
  60. local -a source_files=(**/(CMakeLists.txt|*.cmake)(.N))
  61. source_files=(${source_files:#(build_*)/*})
  62. local -a format_args=()
  63. if (( _loglevel > 2 )) format_args+=(--log-level debug)
  64. ;;
  65. swift)
  66. local formatter=swift-format
  67. if (( ${+commands[swift-format]} )) {
  68. local swift_format_version=$(swift-format --version)
  69. if ! is-at-least 508.0.0 ${swift_format_version}; then
  70. log_error "swift-format is not version 508.0.0 or above (found ${swift_format_version})."
  71. exit 2
  72. fi
  73. } else {
  74. log_error "No viable swift-format version found (required 508.0.0)"
  75. exit 2
  76. }
  77. local -a source_files=(**/*.swift(.N))
  78. local -a format_args=()
  79. ;;
  80. *) log_error "Invalid formatter specified: ${1}. Valid options are clang-format, cmake-format, and swift-format."; exit 2 ;;
  81. }
  82. local file
  83. local -i num_failures=0
  84. if (( check_only )) {
  85. for file (${source_files}) {
  86. if (( _loglevel > 1 )) log_info "Checking format of ${file}..."
  87. if ! "${formatter}" ${format_args} "${file}" | diff -q "${file}" - &> /dev/null; then
  88. log_error "${file} requires formatting changes."
  89. if (( fail_on_error == 2 )) return 2;
  90. num_failures=$(( num_failures + 1 ))
  91. else
  92. if (( _loglevel > 1 )) log_status "${file} requires no formatting changes."
  93. fi
  94. }
  95. if (( fail_on_error && num_failures )) return 2;
  96. } elif (( ${#source_files} )) {
  97. format_args+=(-i)
  98. "${formatter}" ${format_args} ${source_files}
  99. }
  100. }
  101. run_format() {
  102. if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
  103. if (( ! ${+FORMATTER_NAME} )) typeset -g FORMATTER_NAME=${${(s:-:)ZSH_ARGZERO:t:r}[2]}
  104. typeset -g host_os=${${(L)$(uname -s)}//darwin/macos}
  105. local -i fail_on_error=0
  106. local -i check_only=0
  107. local -i verbosity=1
  108. local -r _version='1.0.0'
  109. fpath=("${SCRIPT_HOME}/.functions" ${fpath})
  110. autoload -Uz log_info log_error log_output set_loglevel log_status log_warning
  111. local -r _usage="
  112. Usage: %B${functrace[1]%:*}%b <option>
  113. %BOptions%b:
  114. %F{yellow} Formatting options%f
  115. -----------------------------------------------------------------------------
  116. %B-c | --check%b Check only, no actual formatting takes place
  117. %F{yellow} Output options%f
  118. -----------------------------------------------------------------------------
  119. %B-v | --verbose%b Verbose (more detailed output)
  120. %B--fail-[never|error] Fail script never/on formatting change - default: %B%F{green}never%f%b
  121. %B--debug%b Debug (very detailed and added output)
  122. %F{yellow} General options%f
  123. -----------------------------------------------------------------------------
  124. %B-h | --help%b Print this usage help
  125. %B-V | --version%b Print script version information"
  126. local -a args
  127. while (( # )) {
  128. case ${1} {
  129. --)
  130. shift
  131. args+=($@)
  132. break
  133. ;;
  134. -c|--check) check_only=1; shift ;;
  135. -v|--verbose) (( _verbosity += 1 )); shift ;;
  136. -h|--help) log_output ${_usage}; exit 0 ;;
  137. -V|--version) print -Pr "${_version}"; exit 0 ;;
  138. --debug) verbosity=3; shift ;;
  139. --fail-never)
  140. fail_on_error=0
  141. shift
  142. ;;
  143. --fail-error)
  144. fail_on_error=1
  145. shift
  146. ;;
  147. --fail-fast)
  148. fail_on_error=2
  149. shift
  150. ;;
  151. *) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
  152. }
  153. }
  154. set -- ${(@)args}
  155. set_loglevel ${verbosity}
  156. invoke_formatter ${FORMATTER_NAME}
  157. }
  158. run_format ${@}