Occasionally, defcustoms change their :type and I fail to update my customizations. How can I get Emacs to list all the variables where customize things there's a type mismatch?


I came up with this:

(defun my-custom-variable-valid-p (variable)
    (let ((w (widget-convert (custom-variable-type variable))))
      (widget-apply w :match (symbol-value variable)))))

(defun my-get-mismatched-variables ()
  (let (ret)
     (lambda (x)
       (when (and (custom-variable-p x)
                  (not (my-custom-variable-valid-p x)))
         (push x ret))))

(defun my-show-mismatched-variables ()
  (help-setup-xref (list #'my-show-mismatched-variables)
                   (called-interactively-p 'interactive))
  (with-help-window (help-buffer)
    (dolist (var (sort (my-get-mismatched-variables)
                       (lambda (a b)
                         (apply #'string-lessp
                                (mapcar #'symbol-name (list a b))))))
      (princ "* ")
      (princ (symbol-name var))
      (with-current-buffer standard-output
          (re-search-backward "* \\(.*\\)" nil t)
          (help-xref-button 1 'help-variable var)))
      (princ "\n"))))

You can then do M-x my-show-mismatched-variables to display a buffer with list of variables (symbols) whose values are mismatched. This list will include defcustoms that were declared with invalid :type as well. (Invalid :type is why I use ignore-errors).

  • Thanks, this doesn't seem to work though. After adding some missing )'s on the end, it always returns nil, even though I know I've set some incorrectly. – Alex Mar 21 '18 at 1:44
  • Sorry, when I edited it I accidentally deleted some parentheses, I fixed it now. – mkcms Mar 21 '18 at 8:51
  • There are still quite a few false positives in there for me... – Alex Mar 22 '18 at 0:56

The command custom-invalid-vars defined in the following elisp snippet displays a buffer with symbols of variables with mismatching customization.

Pityingly it also delivers some false positives.

emacs-version: GNU Emacs (i686-pc-linux-gnu, GTK+ Version 3.10.8) of 2016-04-25

(defun custom-invalid-p (symbol)
  "Return non-nil if SYMBOL has invalid customization."
  (when (get symbol 'custom-type)
    (let* ((type (custom-variable-type symbol))
       (conv (and type (widget-convert type))))
      (and (widgetp conv)
       (null (condition-case nil
             (widget-apply conv :match (symbol-value symbol))
           (error t)))))))

(defun custom-invalid-vars ()
  "Print list of variables with non-matching custom-type."
  (let (ret)
     (lambda (symbol)
       (when (custom-invalid-p symbol)
     (setq ret (cons symbol ret)))))
    (when (called-interactively-p 'any)
      (with-current-buffer (get-buffer-create "*Custom: Invalid Vars*")
    (delete-region (point-min) (point-max))
    (insert (mapconcat #'symbol-name ret "\n"))
    (display-buffer (current-buffer))))

You can use function custom-var-val-satisfies-type-p from library cus-edit+.el to get a list of options whose values do not match their custom types.

C-h f custom-var-val-satisfies-type-p:

custom-var-val-satisfies-type-p is a compiled Lisp function in cus-edit+.el.

(custom-var-val-satisfies-type-p VARIABLE TYPES)

VARIABLE is bound, and its value satisfies a type in the list TYPES.

(defun custom-mismatches ()
  "Show options whose values do not match their custom types."
  (let ((vars  ())
     (lambda (var)
       (when (custom-variable-p var)
         (setq type  (get var 'custom-type))
         (unless (or (not type)
                     (custom-var-val-satisfies-type-p var (list (get var 'custom-type))))
           (push var vars)))))
    (pp-display-expression vars "*Custom Type Mismatches*")

(The reason for checking that (get var 'custom-type) is non-nil is that the "type" nil is satisfied by any value. If a defcustom does not actually use :type then the type is nil.)

See Customizing and Saving for more about cus-edit+.el.


If the option, face, or Customize group is something defined by Emacs itself and not by a 3rd-party library then you can use command customize-changed:

customize-changed is an alias for customize-changed-options.

(customize-changed &optional SINCE-VERSION)

Customize all settings whose meanings have changed in Emacs itself. This includes new user options and faces, and new customization groups, as well as older options and faces whose meanings or default values have changed since the previous major Emacs release.

With argument SINCE-VERSION (a string), customize all settings that were added or redefined since that version.

  • Thanks. I'm looking for something that lists only the customize options that are "mismatched," though, which this doesn't do (unless I'm misunderstanding something?) – Alex Mar 21 '18 at 1:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.