editor/format: refactor (again)

This commit is contained in:
Henrik Lissner 2018-08-29 17:02:49 +02:00
parent d24fce1dcd
commit fd9a3c36ee
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395

View file

@ -72,6 +72,19 @@ function."
((error "Invalid rcs patch or internal error in +format--apply-rcs-patch")))))))
(move-to-column column)))
(defun +format--with-copy-of-buffer (formatter executable mode-result)
"Run formatter in a copy of the current buffer.
Since `format-all' functions (and various formatting functions, like `gofmt')
widen the buffer, in order to only format a region of text, we must make a copy
of the buffer to apply formatting to."
(if (buffer-narrowed-p)
(let ((output (buffer-substring-no-properties (point-min) (point-max))))
(with-temp-buffer
(insert output)
(funcall formatter executable mode-result)))
(funcall formatter executable mode-result)))
;;
;; Public library
@ -79,27 +92,39 @@ function."
;;;###autoload
(defun +format-buffer ()
"Auto-format the source code in the current buffer."
(interactive)
"Format the source code in the current buffer.
See `+format/buffer' for the interactive version of this function, and
`+format|buffer' to use as a `before-save-hook' hook."
(require 'format-all)
(cl-destructuring-bind (formatter mode-result) (format-all-probe)
(cl-destructuring-bind (formatter mode-result)
(format-all-probe)
(unless formatter
(error "Don't know how to format %S code" major-mode))
(let ((f-function (gethash formatter format-all-format-table))
(executable (format-all-formatter-executable formatter)))
(cl-destructuring-bind (output errput first-diff)
(funcall f-function executable mode-result)
(prog1 (cl-case output
((nil) 'error)
((t) 'noop)
(t (erase-buffer)
(insert output)
(list output errput first-diff)))
(with-current-buffer (get-buffer-create "*format-all-errors*")
(erase-buffer)
(unless (= 0 (length errput))
(insert errput)
(display-buffer (current-buffer)))))))))
(+format--with-copy-of-buffer f-function executable mode-result)
(unwind-protect
(cond ((null output) 'error)
((eq output t) 'noop)
((let ((tmpfile (make-temp-file "doom_format"))
(patchbuf (get-buffer-create " *doom format patch*"))
(coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8))
(unwind-protect
(progn
(with-current-buffer patchbuf (erase-buffer))
(with-temp-file tmpfile (erase-buffer) (insert output))
(if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
(message "Buffer is already formatted")
(+format--apply-rcs-patch patchbuf)
(message "Formatted buffer with %s" formatter)))
(kill-buffer patchbuf)
(delete-file tmpfile))
(list output errput first-diff))))
(unless (= 0 (length errput))
(message "Formatter error output:\n%s" errput)))))))
;;
@ -108,9 +133,9 @@ function."
;;;###autoload
(defun +format/buffer ()
"TODO"
"Format the source code in the current buffer."
(interactive)
(+format|buffer))
(+format-buffer))
;;;###autoload
(defun +format/region (beg end)
@ -144,31 +169,5 @@ is selected)."
(add-hook 'before-save-hook #'+format|buffer nil t))
;;;###autoload
(defun +format|buffer ()
"TODO"
(let ((tmpfile (make-temp-file "doom_format"))
(patchbuf (get-buffer-create " *doom format patch*"))
(mode major-mode)
(file buffer-file-name)
(dir default-directory)
(coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8))
(unwind-protect
(save-restriction
(with-current-buffer patchbuf (erase-buffer))
(quiet! (write-region (point-min) (point-max) tmpfile))
(pcase (with-current-buffer (find-file-noselect tmpfile t)
(delay-mode-hooks (funcall mode))
(setq buffer-file-name file
default-directory dir)
(quiet! (+format-buffer))
(quiet! (write-region nil nil tmpfile)))
(`noop (message "Buffer is already formatted"))
(`error (message "Couldn't format the buffer due to errors"))
(_ (if (zerop (call-process-region (point-min) (point-max) "diff" nil patchbuf nil "-n" "-" tmpfile))
(message "Buffer is already formatted")
(+format--apply-rcs-patch patchbuf)
(message "Formatted buffer")))))
(kill-buffer patchbuf)
(delete-file tmpfile))))
(defalias '+format|buffer #'+format-buffer)