In the absence of a .clang-format file, imposing the value of `c-basic-offset` onto clang-format seems like reasonable, default behavior. Like all other cases, this can be disabled by unsetting `apheleia-formatters-respect-indent-level` globally or mode-locally with `setq-hook!` or similar.
123 lines
5.7 KiB
EmacsLisp
123 lines
5.7 KiB
EmacsLisp
;;; editor/format/config.el -*- lexical-binding: t; -*-
|
|
|
|
(defcustom +format-on-save-disabled-modes
|
|
'(sql-mode ; sqlformat is currently broken
|
|
tex-mode ; latexindent is broken
|
|
latex-mode
|
|
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."
|
|
:type '(list symbol))
|
|
|
|
(defvaralias '+format-with 'apheleia-formatter)
|
|
(defvaralias '+format-inhibit 'apheleia-inhibit)
|
|
|
|
|
|
;;
|
|
;;; Bootstrap
|
|
|
|
(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)))))))
|
|
|
|
;; Use the formatter provided by lsp-mode and eglot, if available.
|
|
(when (modulep! +lsp)
|
|
(add-hook 'eglot-managed-mode-hook #'+format-with-lsp-toggle-h)
|
|
(add-hook 'lsp-managed-mode-hook #'+format-with-lsp-toggle-h))
|
|
|
|
:config
|
|
(add-to-list 'doom-debug-variables '(apheleia-log-only-errors . nil))
|
|
(add-to-list 'doom-debug-variables '(apheleia-log-debug-info . t))
|
|
|
|
(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)))
|
|
|
|
;; 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))))
|
|
|
|
|
|
;;
|
|
;; Custom formatters
|
|
|
|
;; Apheleia already has a definition for shfmt, but doesn't assign it to any
|
|
;; major modes, so...
|
|
(add-to-list 'apheleia-mode-alist '(sh-mode . shfmt))
|
|
|
|
;; A psuedo-formatter that dispatches to the appropriate LSP client (via
|
|
;; `lsp-mode' or `eglot') that is capable of formatting. Without +lsp, users
|
|
;; must manually set `+format-with' to `lsp' to use it, or activate
|
|
;; `+format-with-lsp-mode' in the appropriate modes.
|
|
(add-to-list 'apheleia-formatters '(lsp . +format-lsp-buffer))
|
|
|
|
;; Apheleia's default clang-format config doesn't respect `c-basic-offset', so
|
|
;; force it to in the absence of a .clang-format file.
|
|
(setf (alist-get 'clang-format apheleia-formatters)
|
|
`("clang-format"
|
|
"-assume-filename"
|
|
(or (apheleia-formatters-local-buffer-file-name)
|
|
(apheleia-formatters-mode-extension)
|
|
".c")
|
|
(when apheleia-formatters-respect-indent-level
|
|
(unless (locate-dominating-file default-directory ".clang-format")
|
|
(format "--style={IndentWidth: %d}" c-basic-offset)))))
|
|
|
|
;; Apheleia's default config for prettier passes an explicit --tab-width N to
|
|
;; all prettier formatters, respecting your indent settings in Emacs, but
|
|
;; overriding any indent settings in your prettier config files. This changes
|
|
;; it to omit indent switches if any configuration for prettier is present in
|
|
;; the current project.
|
|
(dolist (formatter '(prettier prettier-css prettier-html prettier-javascript
|
|
prettier-json prettier-scss prettier-svelte
|
|
prettier-typescript prettier-yaml))
|
|
(setf (alist-get formatter apheleia-formatters)
|
|
(append (delete '(apheleia-formatters-js-indent "--use-tabs" "--tab-width")
|
|
(alist-get formatter apheleia-formatters))
|
|
'((when apheleia-formatters-respect-indent-level
|
|
(unless (or (cl-loop for file
|
|
in '(".prettierrc"
|
|
".prettierrc.json"
|
|
".prettierrc.yml"
|
|
".prettierrc.yaml"
|
|
".prettierrc.json5"
|
|
".prettierrc.js" "prettier.config.js"
|
|
".prettierrc.mjs" "prettier.config.mjs"
|
|
".prettierrc.cjs" "prettier.config.cjs"
|
|
".prettierrc.toml")
|
|
if (locate-dominating-file default-directory file)
|
|
return t)
|
|
(when-let ((pkg (locate-dominating-file default-directory "package.json")))
|
|
(require 'json)
|
|
(let ((json-key-type 'alist))
|
|
(assq 'prettier
|
|
(json-read-file (expand-file-name "package.json" pkg))))))
|
|
(apheleia-formatters-indent "--use-tabs" "--tab-width"))))))))
|