C: Auto-format with clang-format or uncrustify on save

master
Pierre Neidhardt 2018-11-08 12:35:54 +01:00
parent d7db9c58d2
commit 051ce2b1f0
1 changed files with 41 additions and 7 deletions

View File

@ -70,12 +70,7 @@ restored."
(when makefile-dir
(compile (format "make -k -C %s clean" (shell-quote-argument makefile-dir))))))
;;; It is tempting to add `ambrevar/cc-fmt' to the hook:
;; (add-hook 'before-save-hook 'ambrevar/cc-prettify nil t)
;;; Unlike Go however, there is no formatting standard and thus this would break
;;; the formatting rules of every third-party C file that does not follow the
;;; same style.
(defun ambrevar/cc-prettify ()
(defun ambrevar/cc-format-with-uncrustify (&optional cfg-file)
"Run uncrustify(1) on current buffer or region."
(interactive)
(let (status
@ -85,13 +80,51 @@ restored."
(setq start (region-beginning) end (region-end))
(setq start (point-min) end (point-max)))
(setq status
(call-process-region start end "uncrustify" nil formatbuf nil "-lc" "-q" "-c" (expand-file-name ".uncrustify.cfg" (getenv "HOME"))))
(call-process-region start end "uncrustify" nil formatbuf nil "-lc" "-q" "-c"
(or cfg-file
(expand-file-name ".uncrustify.cfg" (getenv "HOME")))))
(if (/= status 0)
(error "error running uncrustify")
(delete-region start end)
(insert-buffer-substring formatbuf)
(kill-buffer formatbuf))))
(defun ambrevar/cc-format-file-lookup ()
"Find .clang-format or .uncrustify.cfg in parent folder up to Git root.
Return nil if non is found or if not a Git repository."
(unless (require 'magit nil 'noerror)
(error "Magit is missing"))
(when (or (magit-get-current-branch) (magit-get-current-tag))
(let ((git-root (magit-rev-parse "--show-toplevel"))
(default-directory default-directory))
(while (and (string= (magit-rev-parse "--show-toplevel") git-root)
(not (file-exists-p ".clang-format"))
(not (file-exists-p ".uncrustify.cfg")))
(cd ".."))
(or (and (file-exists-p ".clang-format")
(expand-file-name ".clang-format" default-directory))
(and (file-exists-p ".uncrustify.cfg")
(expand-file-name ".uncrustify.cfg" default-directory))))))
(defun ambrevar/cc-format ()
"Format C file.
It uses `ambrevar/cc-format-file-lookup' to find the format rules.
This is suitable for a `before-save-hook'."
(interactive)
(let ((cfg-file (ambrevar/cc-format-file-lookup)))
(cond
((and (string= (file-name-base cfg-file) ".clang-format")
(require 'clang-format nil 'noerror))
(clang-format-buffer))
((and (string= (file-name-base cfg-file) ".uncrustify.cfg")
(executable-find "uncrustify"))
(ambrevar/cc-format-with-uncrustify cfg-file)))))
(defun ambrevar/cc-turn-on-format ()
"Add `ambrevar/cc-format' to `before-save-hook' locally.
You can add your mode hook (e.g. `c-mode-hook')."
(add-hook 'before-save-hook 'ambrevar/cc-format nil 'local))
;;; GMP documentation
(with-eval-after-load "info-look"
(let ((mode-value (assoc 'c-mode (assoc 'symbol info-lookup-alist))))
@ -147,6 +180,7 @@ restored."
(dolist (hook '(c-mode-hook c++-mode-hook))
(when (require 'company nil t)
(add-hook hook 'company-mode))
(add-hook hook 'ambrevar/cc-turn-on-format)
(add-hook hook 'ambrevar/cc-set-compiler))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;