refactor(format): redesign module
Rather than wrap Apheleia in custom formatting logic, I now use Apheleia's own machinary to integrate into LSP and Eglot, which is less complexity to maintain. It also makes settings +format-with a more reliable option for per-project or per-file configuration. This also adds a +format/org-src-block command, which I'll incorporate into the org module in a follow-up commit. Ref: #7685
This commit is contained in:
parent
b0e16dc243
commit
8072762de8
2 changed files with 90 additions and 142 deletions
|
@ -1,87 +1,79 @@
|
|||
;;; editor/format/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar +format-on-save-disabled-modes
|
||||
(defcustom +format-on-save-disabled-modes
|
||||
'(sql-mode ; sqlformat is currently broken
|
||||
tex-mode ; latexindent is broken
|
||||
latex-mode
|
||||
org-msg-edit-mode) ; doesn't need a formatter
|
||||
"A list of major modes in which to not reformat the buffer upon saving.
|
||||
If it is t, it is disabled in all modes, the same as if the +onsave flag
|
||||
wasn't used at all.
|
||||
If nil, formatting is enabled in all modes.
|
||||
Irrelevant if you do not have the +onsave flag enabled for this module.")
|
||||
|
||||
(defvar +format-preserve-indentation t
|
||||
"If non-nil, the leading indentation is preserved when formatting the whole
|
||||
buffer. This is particularly useful for partials.
|
||||
If it is t, it is disabled in all modes, the same as if the +onsave flag wasn't
|
||||
used at all.
|
||||
If nil, formatting is enabled in all modes."
|
||||
:type '(list symbol))
|
||||
|
||||
Indentation is always preserved when formatting regions.")
|
||||
|
||||
(defvar +format-with-lsp t
|
||||
(defcustom +format-with-lsp t
|
||||
"If non-nil, format with LSP formatter if it's available.
|
||||
|
||||
LSP formatter is provided by either `lsp-mode' or `eglot'.
|
||||
|
||||
This can be set buffer-locally with `setq-hook!' to disable LSP formatting in
|
||||
select buffers.
|
||||
This has no effect on the +onsave flag, apheleia will always be used there.")
|
||||
select buffers, from a project's .dir-locals.el file, or as a file-local
|
||||
variable."
|
||||
:type 'boolean
|
||||
:safe 'booleanp)
|
||||
|
||||
(defvaralias '+format-with 'apheleia-formatter
|
||||
"Set this to explicitly use a certain formatter for the current buffer.")
|
||||
(defvaralias '+format-with 'apheleia-formatter)
|
||||
|
||||
(defvar +format-functions
|
||||
'(+format-in-org-src-blocks-fn
|
||||
+format-with-lsp-fn
|
||||
+format-with-eglot-fn)
|
||||
"A list of functions to run when formatting a buffer or region.
|
||||
|
||||
Each function is given three arguments: the starting point, end point, and a
|
||||
symbol indicating the type of operation being requested (as a symbol: either
|
||||
`region' or `buffer').
|
||||
|
||||
The first function to return non-nil will abort all functions after it,
|
||||
including Apheleia itself.")
|
||||
|
||||
;;
|
||||
;;; Bootstrap
|
||||
|
||||
(when (modulep! +onsave)
|
||||
(add-hook 'doom-first-file-hook #'apheleia-global-mode))
|
||||
|
||||
(defun +format-maybe-inhibit-h ()
|
||||
"Check if formatting should be disabled for current buffer.
|
||||
(use-package! apheleia
|
||||
:defer t
|
||||
:init
|
||||
(when (modulep! +onsave)
|
||||
(add-hook 'doom-first-file-hook #'apheleia-global-mode)
|
||||
;; apheleia autoloads `apheleia-inhibit-functions' so it will be immediately
|
||||
;; available to mutate early.
|
||||
(add-hook! 'apheleia-inhibit-functions
|
||||
(defun +format-maybe-inhibit-h ()
|
||||
"Check if formatting should be disabled for current buffer.
|
||||
This is controlled by `+format-on-save-disabled-modes'."
|
||||
(or (eq major-mode 'fundamental-mode)
|
||||
(string-blank-p (buffer-name))
|
||||
(eq +format-on-save-disabled-modes t)
|
||||
(not (null (memq major-mode +format-on-save-disabled-modes)))))
|
||||
(or (eq major-mode 'fundamental-mode)
|
||||
(string-blank-p (buffer-name))
|
||||
(eq +format-on-save-disabled-modes t)
|
||||
(not (null (memq major-mode +format-on-save-disabled-modes)))))))
|
||||
|
||||
|
||||
(after! apheleia
|
||||
:config
|
||||
(add-to-list 'doom-debug-variables '(apheleia-log-only-errors . nil))
|
||||
|
||||
(when (modulep! +onsave)
|
||||
(add-to-list 'apheleia-inhibit-functions #'+format-maybe-inhibit-h)))
|
||||
;; Use the formatter provided by lsp-mode and eglot, if they are available and
|
||||
;; `+format-with-lsp' is non-nil.
|
||||
(cond ((modulep! :tools lsp +eglot)
|
||||
(add-to-list 'apheleia-formatters '(eglot . +format-eglot-buffer))
|
||||
(add-hook 'eglot-managed-hook #'+format-toggle-eglot-formatter-h))
|
||||
((modulep! :tools lsp)
|
||||
(add-to-list 'apheleia-formatters '(lsp . +format-lsp-buffer))
|
||||
(add-hook 'lsp-configure-hook #'+format-enable-lsp-formatter-h)
|
||||
(add-hook 'lsp-unconfigure-hook #'+format-disable-lsp-formatter-h)))
|
||||
|
||||
(defadvice! +format--inhibit-reformat-on-prefix-arg-a (orig-fn &optional arg)
|
||||
"Make it so \\[save-buffer] with prefix arg inhibits reformatting."
|
||||
:around #'save-buffer
|
||||
(let ((apheleia-mode (and apheleia-mode (memq arg '(nil 1)))))
|
||||
(funcall orig-fn)))
|
||||
|
||||
;;
|
||||
;;; Hacks
|
||||
|
||||
(defadvice! +format--inhibit-reformat-on-prefix-arg-a (orig-fn &optional arg)
|
||||
"Make it so \\[save-buffer] with prefix arg inhibits reformatting."
|
||||
:around #'save-buffer
|
||||
(let ((apheleia-mode (and apheleia-mode (memq arg '(nil 1)))))
|
||||
(funcall orig-fn)))
|
||||
|
||||
(add-hook!
|
||||
'apheleia-post-format-hook
|
||||
;; HACK `web-mode' doesn't update syntax highlighting after arbitrary buffer
|
||||
;; modifications, so we must trigger refontification manually.
|
||||
(defun +format--fix-web-mode-fontification-h ()
|
||||
(when (eq major-mode 'web-mode)
|
||||
(setq web-mode-fontification-off nil)
|
||||
(when (and web-mode-scan-beg web-mode-scan-end global-font-lock-mode)
|
||||
(save-excursion
|
||||
(font-lock-fontify-region web-mode-scan-beg web-mode-scan-end)))))
|
||||
|
||||
(defun +format--refresh-vc-gutter-h ()
|
||||
(when (fboundp '+vc-gutter-update-h)
|
||||
(+vc-gutter-update-h))))
|
||||
;; HACK: Apheleia suppresses notifications that the current buffer has
|
||||
;; changed, so plugins that listen for them need to be manually informed:
|
||||
(add-hook!
|
||||
'apheleia-post-format-hook
|
||||
(defun +format--update-web-mode-h ()
|
||||
(when (eq major-mode 'web-mode)
|
||||
(setq web-mode-fontification-off nil)
|
||||
(when (and web-mode-scan-beg web-mode-scan-end global-font-lock-mode)
|
||||
(save-excursion
|
||||
(font-lock-fontify-region web-mode-scan-beg web-mode-scan-end)))))
|
||||
(defun +format--update-vc-gutter-h ()
|
||||
(when (fboundp '+vc-gutter-update-h)
|
||||
(+vc-gutter-update-h)))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue