cosmopolitan/tool/emacs/cosmo-format.el
Justine Tunney 416fd86676 Make improvements
- Emulator can now test the αcτµαlly pδrταblε εxεcµταblε bootloader

- Whipped up a webserver named redbean. It services 150k requests per
  second on a single core. Bundling assets inside zip enables extremely
  fast serving for two reasons. The first is that zip central directory
  lookups go faster than stat() system calls. The second is that both
  zip and gzip content-encoding use DEFLATE, therefore, compressed
  responses can be served via the sendfile() system call which does an
  in-kernel copy directly from the zip executable structure. Also note
  that red bean zip executables can be deployed easily to all platforms,
  since these native executables work on Linux, Mac, BSD, and Windows.

- Address sanitizer now works very well
2020-09-14 00:02:34 -07:00

130 lines
4.5 KiB
EmacsLisp

;;; cosmo-format.el --- Cosmopolitan Clang-Format Integration
;; Author: Justine Tunney <jtunney@gmail.com>
;; Version: 0.1.0
;; License: Public Domain
;; Keywords: c c++ clang
;; To the extent possible under law, Justine Tunney has waived all
;; copyright and related or neighboring rights to this file, as it is
;; written in the following disclaimers: <http://unlicense.org/> and
;; <http://creativecommons.org/publicdomain/zero/1.0/>
;;; Commentary:
;;
;; This module automates indentation, whitespace, and other stylistic
;; concerns while editing C/C++ source files. The clang-format program,
;; if present on the system, is run each time a buffer is saved.
;;; Installation:
;;
;; Put the following in your .emacs.d/init.el file:
;;
;; (require 'cosmo-format)
;;
;; Put this file in the root of your project:
;;
;; printf '---\nBasedOnStyle: Google\n...\n' >.clang-format
;;
;; Any buffer whose pathname matches `cosmo-format-path-regex' will
;; be formatted automatically on save if:
;;
;; 1. It's able to find the clang-format program, or
;; `cosmo-format-bin' is customized.
;;
;; 2. There's a .clang-format file up the directory tree, or
;; `cosmo-format-arg' is customized; in which case, it is
;; recommended that it be customized buffer locally.
;;
;; For all other cases, there are no latency penalties (i.e. superfluous
;; i/o syscalls) or risks to leaving this enabled globally.
;;; Code:
(defcustom cosmo-format-bin nil
"Explicit command or pathname of clang-format program."
:type 'string
:group 'cosmo-format)
(defcustom cosmo-format-arg nil
"Explicit argument to clang-format program."
:type 'string
:group 'cosmo-format)
(defcustom cosmo-format-modes '(c-mode
c++-mode
java-mode
protobuf-mode)
"List of major-modes that need clang-format."
:type '(repeat symbol)
:group 'cosmo-format)
(defcustom cosmo-format-exts '("c" "cc" "h" "inc" ;; c/c++
"hh" "cpp" "hpp" ;; ms c/c++
"rl" ;; ragel
"proto") ;; protobuf
"List of pathname extensions that need clang-format."
:type '(repeat string)
:group 'cosmo-format)
(defcustom cosmo-format-blacklist '()
"List of files to ignore, matched by basename."
:type '(repeat string)
:group 'cosmo-format)
(defvar cosmo--clang-format-bin)
(defmacro cosmo-memoize (var mvar form)
"Return VAR or evaluate FORM memoized locally to MVAR."
`(cond (,var ,var)
((fboundp (quote ,mvar))
(cond ((eq ,mvar 'null) nil)
(t ,mvar)))
(t (let ((res ,form))
(setq-local ,mvar (or res 'null))
res))))
(defun cosmo--find-clang-format-bin ()
(cosmo-memoize cosmo-format-bin
cosmo--clang-format-bin
(or (executable-find "clang-format-10")
(executable-find "clang-format-9")
(executable-find "clang-format-8")
(executable-find "clang-format-7")
(executable-find "clang-format"))))
(defun cosmo-format ()
"Beautifies source code in current buffer."
(interactive)
(when (and (memq major-mode cosmo-format-modes)
(member (file-name-extension (buffer-file-name))
cosmo-format-exts)
(not (member (file-name-nondirectory (buffer-name))
cosmo-format-blacklist)))
(let ((bin (cosmo--find-clang-format-bin)))
(when bin
(let ((p (point))
(tmp (make-temp-file "cosmo-format"))
(arg (or cosmo-format-arg
(and (locate-dominating-file
(buffer-file-name)
".clang-format")
"-style=file"))))
(when arg
(message arg)
(write-region nil nil tmp)
(let ((buf (get-buffer-create "*clang-format*"))
(exe (cosmo--find-clang-format-bin)))
(with-current-buffer buf
(call-process exe tmp t nil arg))
(replace-buffer-contents buf)
(kill-buffer buf)
(delete-file tmp nil))))))))
;; Emacs 26.3+ needed for replace-buffer-contents; so worth it!!
(unless (version-list-< (version-to-list emacs-version) '(26 3))
(add-hook 'before-save-hook 'cosmo-format))
(provide 'cosmo-format)
;;; cosmo-format.el ends here