Skip to content

Instantly share code, notes, and snippets.

@choppsv1
Created May 19, 2019 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save choppsv1/c45a857ced56d4f9713eb7a555cfba2d to your computer and use it in GitHub Desktop.
Save choppsv1/c45a857ced56d4f9713eb7a555cfba2d to your computer and use it in GitHub Desktop.
Auto-format vpp C files on save in Emacs using "indent"
(defun vpp-format-buffer ()
(if (and (eq major-mode 'c++-mode)
(boundp 'clang-format-buffer))
(clang-format-buffer)
(vpp-indent-format-buffer)))
(defun vpp-maybe-format-buffer ()
"Reformat buffer if contains VPP magic"
(when (save-excursion
(goto-char (point-min))
(search-forward "fd.io coding-style-patch-verification: ON" nil t))
(vpp-format-buffer)))
(defun vpp-maybe-format-buffer-on-save ()
(add-hook 'before-save-hook 'vpp-maybe-format-buffer nil t))
(add-hook 'c-mode-hook 'vpp-maybe-format-buffer-on-save)
(add-hook 'c++-mode-hook 'vpp-maybe-format-buffer-on-save)
;;
;; The complexity here is to catch when indent is non-deterministic, and display
;; the resulting diff.
;;
(defun vpp-indent-format-buffer ()
"Reformat the buffer using 'indent'"
(interactive)
(let ((oldbuf (current-buffer))
fmtbuf
errbuf)
(with-temp-buffer
(insert-buffer-substring oldbuf)
(shell-command-on-region (point-min) (point-max) "indent -gnu" (current-buffer) t nil t)
(unless (= 0 (compare-buffer-substrings oldbuf nil nil (current-buffer) nil nil))
(setq fmtbuf (current-buffer))
(with-temp-buffer
(insert-buffer-substring fmtbuf)
(shell-command-on-region (point-min) (point-max) "indent -gnu" (current-buffer) t nil t)
(if (not (= 0 (compare-buffer-substrings fmtbuf nil nil (current-buffer) nil nil)))
(progn
(message "INDENT FAILED second invocation different from first")
(let ((cbuf (current-buffer))
(tmp1 (make-temp-file "vppfmt1"))
(tmp2 (make-temp-file "vppfmt2")))
(unwind-protect
(progn
(with-temp-file tmp2 (insert-buffer-substring cbuf))
(with-temp-file tmp1 (insert-buffer-substring fmtbuf))
(let ((newbuf (get-buffer-create "*vpp-indent-non-deterministic*")))
(shell-command (format "diff -u %s %s" tmp1 tmp2) newbuf)
(if (= 0 (buffer-size newbuf))
(kill-buffer newbuf)
(setq errbuf newbuf))))
(delete-file tmp1)
(delete-file tmp2))))
(with-current-buffer oldbuf
(if (boundp 'replace-buffer-contents)
;; emacs 26 retains properties in buffer
(replace-buffer-contents fmtbuf)
(let ((oldpoint (point)))
(erase-buffer)
(insert-buffer-substring fmtbuf)
(goto-char (min (point-max) oldpoint)))))))))
(if errbuf (display-buffer errbuf))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment