I want to customize environment while the specific package is installed properly. How to check whether some package is installed in elisp? Something like this?:
(if (require 'ecb)
(progn (setq ....))
(message "ECB not installed!"))
I want to customize environment while the specific package is installed properly. How to check whether some package is installed in elisp? Something like this?:
(if (require 'ecb)
(progn (setq ....))
(message "ECB not installed!"))
tripleee's answer is a handy example of error handling, but unnecessary in this instance.
(when (require 'some-library nil 'noerror)
do-things)
That 'noerror
can be any non-nil value, but of course it's more descriptive this way. I often see :noerror
used as well, but I've no idea if there's any particular advantage to using a keyword argument over a symbol (comments, anyone? I'm quite interested to know).
require is a built-in function in
C source code
.(require FEATURE &optional FILENAME NOERROR)
If feature FEATURE is not loaded, load it from FILENAME.
If FEATURE is not a member of the listfeatures
, then the feature
is not loaded; so load the file FILENAME.
If FILENAME is omitted, the printname of FEATURE is used as the file name,
andload
will try to load this name appended with the suffix.elc
or
.el
, in that order. The name without appended suffix will not be used.
Seeget-load-suffixes
for the complete list of suffixes.
If the optional third argument NOERROR is non-nil,
then return nil if the file is not found instead of signaling an error.
Normally the return value is FEATURE.
The normal messages at start and end of loading FILENAME are suppressed.
AUCTeX
because AUCTeX
cannot be required. You need to use package-installed-p
for AUCTeX
–
Dylandylana auctex
does seem a bit unusual. It looks like you could test for tex-site
after loading auctex
though. e.g. (load "auctex" :noerror) (when (require 'tex-site nil :noerror) ...)
–
Tanta Why not using "featurep"?
(featurep FEATURE &optional SUBFEATURE)
Return t if FEATURE is present in this Emacs.
(if (featurep 'ecb)
(message "ECB is there!"))
The (require)
will throw an error if it fails. That should really be all you need.
If you want to configure ECB's behavior only when it is available, look primarily into adding stuff to ecb-hook
-- this is the normal way to configure an Emacs package conditionally.
If no hook is available, or you want to roll it by hand for some reason, try something like
(eval-after-load 'ecb '(setq ecb-be-more-like-better-yes-p t))
If you really really want to roll this by hand, you can trap the error from a failed require
like this:
(condition-case nil
(progn
(require 'ecb)
(setq ecb-be-more-like-better-yes-p t) )
(file-error (message "ECB not available; not configuring") ))
Note that the condition-case
will catch any file-error
from inside the progn
so you want to make sure you don't do any other file operations inside. Ultimately you may want to put just the require
inside a condition-case
and use that as the condition for your original if
form, but this is already getting out of hand ...
(if (condition-case nil (require 'ecb) (error nil))
(setq ecb-be-more-like-better-yes-p t)
(message "ECB not available; not configuring") )
eval-after-load
seems not load the package. So I changed to the answer below: (when (...)) –
Celeriac eval-after-load
is to specify a deferred action to execute if and when you do load the specified package. It's useful for avoiding unnecessary setup when you launch Emacs for a task which does not involve loading ecb
(batch byte compilation is a perennial example). –
Hume For people wondering how to check if a package.el package is installed, use package-installed-p
.
The simplest answer is to use require
and eval-after-load
as stated in other answers.
However that is not always convenient, such as in a function called by a mode hook that wants to activate another minor mode but only if the package for it is installed. In this case featurep
is relevant.
Emacs packages increasingly use autoload to improve startup time. If you test for the presence of a package by using require
then you are wearing the cost of loading the file(s). If using ELPA/MELPA/Marmalade packages (available by default since version 24) then many packages may be available in an as-yet unloaded state, but a package foo
with autoloads will provide a feature foo-autoloads
. I wrote a function that is useful for testing whether a package is available in terms of already being loaded or set to autoload.
(defun autofeaturep (feature)
"For a feature symbol 'foo, return a result equivalent to:
(or (featurep 'foo-autoloads) (featurep 'foo))
Does not support subfeatures."
(catch 'result
(let ((feature-name (symbol-name feature)))
(unless (string-match "-autoloads$" feature-name)
(let ((feature-autoloads (intern-soft (concat feature-name "-autoloads"))))
(when (and feature-autoloads (featurep feature-autoloads))
(throw 'result t))))
(featurep feature))))
Four years late on this question, but... here's a simple macro that will do this for you.
(defmacro when-feature-loaded (feature &rest body)
"Executes BODY if and only if FEATURE is loaded."
(declare (indent defun))
`(when (featurep ,module)
@,body))
For example:
(when-feature-loaded 'foo
(message "foo is loaded!"))
Here's another version with an "else" case, in case you need to handle that as well.
(defmacro if-feature-loaded (module then-form else-form)
"Executes THEN-FORM if and only if MODULE is already loaded, otherwise executes ELSE-FORM."
(declare (indent 2))
`(if (featurep ,module)
,then-form
,else-form))
module
-> feature
in the first snippet. –
Infective N.B.: Using (require ..)
will load the package, which defeats the benefit of autoloads (deferred loading).
I use this in my code to configure functions which are autoloaded:
(when (fboundp 'some-function)
...)
I have this in my init.el:
(when (fboundp 'ace-select-window)
(keymap-global-set "M-s-u" 'ace-select-window))
If you have ace-window
installed, you can test this yourself by copying it into your own init file, restarting Emacs, and running:
(autoloadp (symbol-function 'ace-select-window))
It should return T
. Then run the command, and execute that snippet again; it should return nil
.
(newbie tip: Hit altshift:, then enter that, and press enter)
This avoids loading your package just to configure it (which is the point of autoloading).
(newbie tip nr 2: using fbound
is for functions; use boundp
for values)
© 2022 - 2024 — McMap. All rights reserved.
'noerror
there is defined, so any non-nil value will work. I've been usingt
myself. – Tamis