diff --git a/modules/editor/format/autoload/format.el b/modules/editor/format/autoload/format.el index a157f61ac..881445dba 100644 --- a/modules/editor/format/autoload/format.el +++ b/modules/editor/format/autoload/format.el @@ -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)