Custom formatter (uncrustify) not applied to buffer

What happened?

I have setup a custom formatter in my config.el:

(set-formatter! 'uncrustify '("uncrustify" "-q"
                              ("-f" "%s" buffer-file-name)))

and enabled it in my projects dir-locals.el:

((c-mode . ((+format-with 'uncrustify))))

I’ve verified that in my buffers +format-with is set to 'uncrustify.

Trying to format with SPC:+format/bufferRET will not format the buffer. No errors are being shown in *format-all-errors*.

Some detective work

From format-all.el:

(defun format-all-buffer ()
  (interactive)
  (cl-destructuring-bind (formatter mode-result) (format-all--probe)
    (if formatter
        (format-all-buffer--with formatter mode-result)
      (error "Don't know how to format %S code" major-mode))))

(format-all-probe) evaluates to (('uncrustify) t) so we end up calling

(format-all-buffer--with '('uncrustify) t) which produces a backtrace (see below)

Interestingly (format-all-buffer--with 'uncrustify t) works just fine

Am I doing something wrong? Is this a bug? Is (format-all-probe) returning the right thing here?

To the best of my (admittedly limited) ability I followed the examples from SPChfset-formatter!, so any pointers would be greatly appreciated!

Backtrace

If I eval (format-all-buffer) or (format-all-buffer--with '('uncrustify) t) I run into an error:

Debugger entered--Lisp error: (void-function nil)
  nil(nil t)
  funcall(nil nil t)
  (progn (insert output) (let* ((--cl-var-- (cl-remove-if-not #'listp (buffer-local-variables origin-buffer))) (val nil) (var nil)) (while (consp --cl-var--) (setq val (car --cl-var--) var (car-safe (prog1 val (setq val (cdr val))))) (if (eq var 'enable-multibyte-characters) (progn) (if (string-match-p (symbol-name var) "-\\(hook\\|functions\\)$") (progn) (set (make-local-variable var) val))) (setq --cl-var-- (cdr --cl-var--))) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn (indent-rigidly (point-min) (point-max) (- indent)))) (funcall f-function executable mode-result))
  (unwind-protect (progn (insert output) (let* ((--cl-var-- (cl-remove-if-not #'listp (buffer-local-variables origin-buffer))) (val nil) (var nil)) (while (consp --cl-var--) (setq val (car --cl-var--) var (car-safe (prog1 val (setq val ...)))) (if (eq var 'enable-multibyte-characters) (progn) (if (string-match-p (symbol-name var) "-\\(hook\\|functions\\)$") (progn) (set (make-local-variable var) val))) (setq --cl-var-- (cdr --cl-var--))) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn (indent-rigidly (point-min) (point-max) (- indent)))) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil)))
  (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (insert output) (let* ((--cl-var-- (cl-remove-if-not #'listp (buffer-local-variables origin-buffer))) (val nil) (var nil)) (while (consp --cl-var--) (setq val (car --cl-var--) var (car-safe (prog1 val ...))) (if (eq var 'enable-multibyte-characters) (progn) (if (string-match-p ... "-\\(hook\\|functions\\)$") (progn) (set ... val))) (setq --cl-var-- (cdr --cl-var--))) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn (indent-rigidly (point-min) (point-max) (- indent)))) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil))))
  (progn (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (insert output) (let* ((--cl-var-- (cl-remove-if-not ... ...)) (val nil) (var nil)) (while (consp --cl-var--) (setq val (car --cl-var--) var (car-safe ...)) (if (eq var ...) (progn) (if ... ... ...)) (setq --cl-var-- (cdr --cl-var--))) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn (indent-rigidly (point-min) (point-max) (- indent)))) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil)))))
  (unwind-protect (progn (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (insert output) (let* ((--cl-var-- ...) (val nil) (var nil)) (while (consp --cl-var--) (setq val ... var ...) (if ... ... ...) (setq --cl-var-- ...)) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn (indent-rigidly ... ... ...))) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil))))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (insert output) (let* (... ... ...) (while ... ... ... ...) nil) (setq indent (+format--current-indentation)) (if (> indent 0) (progn ...)) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil))))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))
  (let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (let* ((modified (buffer-modified-p)) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn (insert output) (let* ... ... nil) (setq indent ...) (if ... ...) (funcall f-function executable mode-result)) (if modified nil (restore-buffer-modified-p nil))))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
  (let ((output (buffer-substring-no-properties (point-min) (point-max))) (origin-buffer (or (buffer-base-buffer) (current-buffer))) write-file-functions before-save-hook after-save-hook kill-buffer-query-functions kill-buffer-hook) (let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (let* ((modified ...) (buffer-undo-list t) (inhibit-read-only t) (inhibit-modification-hooks t)) (unwind-protect (progn ... ... ... ... ...) (if modified nil ...)))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))))
  (let* ((val (let ((output (buffer-substring-no-properties (point-min) (point-max))) (origin-buffer (or (buffer-base-buffer) (current-buffer))) write-file-functions before-save-hook after-save-hook kill-buffer-query-functions kill-buffer-hook) (let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn ...) (and ... ...)))))) (x21 (car val)) (x22 (cdr val)) (x23 (car x22)) (x24 (cdr x22))) (let ((errput x23) (output x21)) (let* ((val (cond ((null output) :error) ((eq output t) :already-formatted) (t :reformatted)))) (let ((status val)) (unwind-protect (if (eq status :reformatted) (progn (let ... ... ...))) (format-all--show-or-hide-errors errput) (goto-char (point-min)) (forward-line (1- old-line-number)) (let ((line-length ...)) (goto-char (+ ... ...))) (run-hook-with-args 'format-all-after-format-functions formatter status) (message (cond (... "Formatting error") (... "Already formatted") (... ...) (t nil))))))))
  (let ((f-function (gethash formatter format-all--format-table)) (executable (format-all--formatter-executable formatter)) (indent 0) (old-line-number (line-number-at-pos)) (old-column (current-column))) (let* ((val (let ((output (buffer-substring-no-properties ... ...)) (origin-buffer (or ... ...)) write-file-functions before-save-hook after-save-hook kill-buffer-query-functions kill-buffer-hook) (let ((temp-buffer ...)) (save-current-buffer (set-buffer temp-buffer) (unwind-protect ... ...))))) (x21 (car val)) (x22 (cdr val)) (x23 (car x22)) (x24 (cdr x22))) (let ((errput x23) (output x21)) (let* ((val (cond (... :error) (... :already-formatted) (t :reformatted)))) (let ((status val)) (unwind-protect (if (eq status :reformatted) (progn ...)) (format-all--show-or-hide-errors errput) (goto-char (point-min)) (forward-line (1- old-line-number)) (let (...) (goto-char ...)) (run-hook-with-args 'format-all-after-format-functions formatter status) (message (cond ... ... ... ...))))))))
  (cond ((eq formatter 'lsp) (call-interactively (if +format-region-p #'lsp-format-region #'lsp-format-buffer))) ((eq formatter 'eglot) (call-interactively (if +format-region-p #'eglot-format #'eglot-format-buffer))) ((let ((f-function (gethash formatter format-all--format-table)) (executable (format-all--formatter-executable formatter)) (indent 0) (old-line-number (line-number-at-pos)) (old-column (current-column))) (let* ((val (let (... ... write-file-functions before-save-hook after-save-hook kill-buffer-query-functions kill-buffer-hook) (let ... ...))) (x21 (car val)) (x22 (cdr val)) (x23 (car x22)) (x24 (cdr x22))) (let ((errput x23) (output x21)) (let* ((val ...)) (let (...) (unwind-protect ... ... ... ... ... ... ...))))))))
  +format-buffer-a(('uncrustify) t)
  apply(+format-buffer-a (('uncrustify) t))
  format-all-buffer--with(('uncrustify) t)
  (if formatter (format-all-buffer--with formatter mode-result) (error "Don't know how to format %S code" major-mode))
  (let* ((--cl-rest-- (format-all--probe)) (formatter (if (= (length --cl-rest--) 2) (car-safe (prog1 --cl-rest-- (setq --cl-rest-- (cdr --cl-rest--)))) (signal 'wrong-number-of-arguments (list '(formatter mode-result) (length --cl-rest--))))) (mode-result (car --cl-rest--))) (if formatter (format-all-buffer--with formatter mode-result) (error "Don't know how to format %S code" major-mode)))
  format-all-buffer()
  eval((format-all-buffer) t)
  eval-expression((format-all-buffer) nil nil 127)
  funcall-interactively(eval-expression (format-all-buffer) nil nil 127)
  call-interactively(eval-expression nil nil)
  command-execute(eval-expression)

System information


Loading data dump...

Of course I found my issue only minutes after posting the question…

((c-mode . ((+format-with 'uncrustify))))

should have been

((c-mode . ((+format-with . uncrustify))))

1 Like

I’ve verified that in my buffers +format-with is set to 'uncrustify.

A potential clue here would be that the value shown by helpful-variable would actually be ('uncrustify), a list with a single element, rather than 'uncrustify, the symbol alone.

The manual section on cons cell types (view in Emacs with M-x eval-expression (info "(elisp) Cons Cell Type") is a concise, illustrative read.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.