It seems that packages will try to load even if it doesn't exist. This occurs even when use-package-check-before-init is set to t. For example the following will crash on startup if lispyville is not installed:
(use-package lispyville
:diminish (lispyville-mode-line-string " 馃嵃")
:hook ((clojure-mode emacs-lisp-mode lisp-mode) . lispyville-mode))
It could be worked around by wrapping everything inside a (with-eval-after-load ...) form, but I prefer to have a way of doing it universally in all use-package definitions to prevent copy-pasting.
use-package-check-before-init only works for :init. It would be nice to be able to control which keywords can run if the package is not available.
Also, this is basically the same as #693 (except that issue may have been specifically for :config; either way, I think only one open issue is needed). What you can do for now is use :if, but this requires using a wrapper around use-package if you want to do it automatically.
How could I define such a wrapper?
Something like this:
(defmacro my-use-package (name &rest args)
(declare (indent 1))
`(use-package ,name
:when (package-installed-p ',name)
,@args))
Yeah that's a good solution. You could also register that default :when handler to use-package-defaults as well.
That's a much better idea. I didn't realize you can have use-package still keep a default value for a keyword even when the keyword is manually specified with use-package-defaults. I personally use locate-library instead since I'm not using package.el. This seems to work well:
(cl-pushnew '(:when
(lambda (package &rest _)
`(locate-library (symbol-name ',package)))
t)
use-package-defaults
:test #'equal)
Most helpful comment
Yeah that's a good solution. You could also register that default
:whenhandler touse-package-defaultsas well.