From 54bde12c0295e008e050a8418c4702b8f3ea4a55 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 5 Oct 2019 15:49:28 +0200 Subject: add uncrustify hook --- bootstrap | 19 +++++ contrib/uncrustify-mode.el | 161 +++++++++++++++++++++++++++++++++++++++++++ contrib/uncrustify.cfg | 78 +++++++++++++++++++++ contrib/uncrustify.el | 13 ++++ contrib/uncrustify.sh | 14 ++++ contrib/uncrustify_precommit | 35 ++++++++++ 6 files changed, 320 insertions(+) create mode 100755 contrib/uncrustify-mode.el create mode 100644 contrib/uncrustify.cfg create mode 100644 contrib/uncrustify.el create mode 100755 contrib/uncrustify.sh create mode 100755 contrib/uncrustify_precommit diff --git a/bootstrap b/bootstrap index 373e5f5e..5fbaf9b7 100755 --- a/bootstrap +++ b/bootstrap @@ -8,5 +8,24 @@ fi echo "$0: Updating submodules" echo | git submodule update --init + +# This is more portable than `which' but comes with +# the caveat of not(?) properly working on busybox's ash: +existence() +{ + command -v "$1" >/dev/null 2>&1 +} + + +if existence uncrustify; then + echo "Installing uncrustify hook and configuration" + # Install uncrustify format symlink (if possible) + ln -s contrib/uncrustify.cfg uncrustify.cfg 2> /dev/null + # Install pre-commit hook (if possible) + ln -s ../../contrib/uncrustify_precommit .git/hooks/pre-commit 2> /dev/null +else + echo "Uncrustify not detected, hook not installed. Please install uncrustify if you plan on doing development" +fi + echo "$0: Running autoreconf" autoreconf -if diff --git a/contrib/uncrustify-mode.el b/contrib/uncrustify-mode.el new file mode 100755 index 00000000..83868c6a --- /dev/null +++ b/contrib/uncrustify-mode.el @@ -0,0 +1,161 @@ +;;; uncrustify-mode.el --- Minor mode to automatically uncrustify. + +;; Copyright (C) 2012 tabi +;; Author: Tabito Ohtani +;; Version: 0.01 +;; Keywords: uncrustify + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Installation: + +;; drop requirements and this file into a directory in your `load-path', +;; and put these lines into your .emacs file. + +;; (require 'uncrustify-mode) +;; (add-hook 'c-mode-common-hook +;; '(lambda () +;; (uncrustify-mode 1))) + +;;; ChangeLog: +;; * 0.0.1: +;; Initial version. + + +;; case +(eval-when-compile + (require 'cl)) + +;;; Variables: + +(defcustom uncrustify-config-path + "~/.uncrustify.cfg" + "uncrustify config file path" + :group 'uncrustify + :type 'file) +(make-variable-buffer-local 'uncrustify-config-path) + +(defcustom uncrustify-bin + "uncrustify -q" + "The command to run uncrustify." + :group 'uncrustify) + +;;; Functions: + +(defun uncrustify-get-lang-from-mode (&optional mode) + "uncrustify lang option" + (let ((m (or mode major-mode))) + (case m + ('c-mode "C") + ('c++-mode "CPP") + ('d-mode "D") + ('java-mode "JAVA") + ('objc-mode "OC") + (t + nil)))) + +(defun uncrustify-point->line (point) + "Get the line number that POINT is on." + ;; I'm not bothering to use save-excursion because I think I'm + ;; calling this function from inside other things that are likely to + ;; use that and all I really need to do is restore my current + ;; point. So that's what I'm doing manually. + (let ((line 1) + (original-point (point))) + (goto-char (point-min)) + (while (< (point) point) + (incf line) + (forward-line)) + (goto-char original-point) + line)) + +(defun uncrustify-invoke-command (lang start-in end-in) + "Run uncrustify on the current region or buffer." + (if lang + (let ((start (or start-in (point-min))) + (end (or end-in (point-max))) + (original-line (uncrustify-point->line (point))) + (cmd (concat uncrustify-bin " -c " uncrustify-config-path " -l " lang)) + (out-buf (get-buffer-create "*uncrustify-out*")) + (error-buf (get-buffer-create "*uncrustify-errors*"))) + + (with-current-buffer error-buf (erase-buffer)) + (with-current-buffer out-buf (erase-buffer)) + + ;; Inexplicably, save-excursion doesn't work to restore the + ;; point. I'm using it to restore the mark and point and manually + ;; navigating to the proper new-line. + (let ((result + (save-excursion + (let ((ret (shell-command-on-region start end cmd t t error-buf nil))) + (if (and + (numberp ret) + (zerop ret)) + ;; Success! Clean up. + (progn + (message "Success! uncrustify modify buffer.") + (kill-buffer error-buf) + t) + ;; Oops! Show our error and give back the text that + ;; shell-command-on-region stole. + (progn (undo) + (with-current-buffer error-buf + (message "uncrustify error: <%s> <%s>" ret (buffer-string))) + nil)))))) + + ;; This goto-line is outside the save-excursion becuase it'd get + ;; removed otherwise. I hate this bug. It makes things so ugly. + (goto-line original-line) + (not result))) + (message "uncrustify not support this mode : %s" major-mode))) + +(defun uncrustify () + (interactive) + (save-restriction + (widen) + (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (region-beginning) (region-end)))) + +(defun uncrustify-buffer () + (interactive) + (save-restriction + (widen) + (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max)))) + +;;; mode + +(defun uncrustify-write-hook () + "Uncrustifys a buffer during `write-file-hooks' for `uncrustify-mode'. + if uncrustify returns not nil then the buffer isn't saved." + (if uncrustify-mode + (save-restriction + (widen) + (uncrustify-invoke-command (uncrustify-get-lang-from-mode) (point-min) (point-max))))) + +;;;###autoload +(define-minor-mode uncrustify-mode + "Automatically `uncrustify' when saving." + :lighter " Uncrustify" + (if (not (uncrustify-get-lang-from-mode)) + (message "uncrustify not support this mode : %s" major-mode) + (if (version<= "24" emacs-version) + (if uncrustify-mode + (add-hook 'write-file-hooks 'uncrustify-write-hook nil t) + (remove-hook 'uncrustify-write-hook t)) + (make-local-hook 'write-file-hooks) + (funcall (if uncrustify-mode #'add-hook #'remove-hook) + 'write-file-hooks 'uncrustify-write-hook)))) + +(provide 'uncrustify-mode) + +;;; uncrustify-mode.el ends here diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg new file mode 100644 index 00000000..f56c8e73 --- /dev/null +++ b/contrib/uncrustify.cfg @@ -0,0 +1,78 @@ +input_tab_size = 2 +output_tab_size = 2 + +indent_columns = 2 +indent_with_tabs = 0 +indent_case_brace = 2 +indent_label=-16 + +code_width=80 +#cmd_width=80 + +# Leave most comments alone for now +cmt_indent_multi=false +sp_cmt_cpp_start=add + +sp_not=add + +sp_func_call_user_paren_paren=remove +sp_inside_fparen=remove +sp_after_cast=add + +ls_for_split_full=true +ls_func_split_full=true +ls_code_width=true + +# Arithmetic operations in wrapped expressions should be at the start +# of the line. +pos_arith=lead + +# Fully parenthesize boolean exprs +mod_full_paren_if_bool=true + +# Braces should be on their own line +nl_fdef_brace=add +nl_enum_brace=add +nl_struct_brace=add +nl_union_brace=add +nl_if_brace=add +nl_brace_else=add +nl_elseif_brace=add +nl_while_brace=add +nl_switch_brace=add + +# no newline between "else" and "if" +nl_else_if=remove + +nl_func_paren=remove +nl_assign_brace=remove + +# No extra newlines that cause noisy diffs +nl_start_of_file=remove +# If there's no new line, it's not a text file! +nl_end_of_file=add + +sp_inside_paren = remove + +sp_arith = add +sp_arith_additive = add + +# We want spaces before and after "=" +sp_before_assign = add +sp_after_assign = add + +# we want "char *foo;" +sp_after_ptr_star = remove +sp_between_ptr_star = remove + +# we want "if (foo) { ... }" +sp_before_sparen = add + +sp_inside_fparen = remove + +# add space before function call and decl: "foo (x)" +sp_func_call_paren = add +sp_func_proto_paren = add +sp_func_proto_paren_empty = add +sp_func_def_paren = add +sp_func_def_paren_empty = add diff --git a/contrib/uncrustify.el b/contrib/uncrustify.el new file mode 100644 index 00000000..2ab6961f --- /dev/null +++ b/contrib/uncrustify.el @@ -0,0 +1,13 @@ +;; suggested integration of uncrustify for Emacs +;; This assumes that the 'uncrustify-mode.el' is +;; installed to '~/.emacs.d/load-path/'. Feel free +;; to put it elsewhere and adjust the load path below! + +;; adding the following to ~/.emacs will then run +;; uncrustify whenever saving a C buffer. + +(add-to-list 'load-path "~/.emacs.d/load-path/") +(require 'uncrustify-mode) +(add-hook 'c-mode-common-hook + '(lambda () + (uncrustify-mode 1))) diff --git a/contrib/uncrustify.sh b/contrib/uncrustify.sh new file mode 100755 index 00000000..e8e05d3e --- /dev/null +++ b/contrib/uncrustify.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -eu + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +if ! uncrustify --version >/dev/null; then + echo "you need to install uncrustify for indentation" + exit 1 +fi + +find "$DIR/../src" \( -name "*.cpp" -o -name "*.c" -o -name "*.h" \) \ + -exec uncrustify -c "$DIR/uncrustify.cfg" --replace --no-backup {} + \ + || true diff --git a/contrib/uncrustify_precommit b/contrib/uncrustify_precommit new file mode 100755 index 00000000..fd29998c --- /dev/null +++ b/contrib/uncrustify_precommit @@ -0,0 +1,35 @@ +#!/bin/sh + +# use as .git/hooks/pre-commit + +exec 1>&2 + +RET=0 +changed=$(git diff --cached --name-only) +crustified="" + +for f in $changed; +do + if echo $f | grep \\.[c,h]\$ > /dev/null + then + # compare result of uncrustify with changes + # + # only change any of the invocations here if + # they are portable across all cmp and shell + # implementations ! + uncrustify -q -c uncrustify.cfg -f $f | cmp -s $f - + if test $? = 1 ; + then + crustified=" $crustified $f" + RET=1 + fi + fi +done + +if [ $RET = 1 ]; +then + echo "Run" + echo "uncrustify --no-backup -c uncrustify.cfg ${crustified}" + echo "before commiting." +fi +exit $RET -- cgit v1.2.3