0

What should I use:

(when (package-installed-p 'ivy)
  (global-set-key (kbd "C-x b") #'ivy-switch-buffer))

or:

(when (fboundp 'ivy-switch-buffer)
  (global-set-key (kbd "C-x b") #'ivy-switch-buffer))

or:

(eval-after-load ivy ...)  ; haven't tested it yet

I try to rebind key based on a package presence. We are in 2021 so it is safe to assume of presence of package.el but what if I installed a package from git/hg?

UPDATE With fboundp & compilation of .emacs it doesn't redefine key.

Works with package-installed-p though... I haven't (ivy-mode +1) so function definition ivy-switch-buffer can be in form of autoload...

5
  • The question is likely to invite opinion-based answers...
    – Drew
    Sep 30, 2020 at 22:21
  • emacs.stackexchange.com/tags/elisp/info
    – Drew
    Sep 30, 2020 at 22:22
  • 1
    If you want to actually make sure the library is loaded then use require. You can do that without raising an error if not found by doing (require 'the-library nil t). See C-h f require.
    – Drew
    Sep 30, 2020 at 22:24
  • require adds delay to boot time. Packages register autoloads to avoid eager loading... I was searching for the way to discover such "registration". package-installed-p & eval-after-load are nice alternatives. update it is for .emacs. For libraries only the require is viable option...
    – gavenkoa
    Oct 4, 2020 at 8:03
  • A soft require (e.g. (require 'foo nil t)) doesn't add delay, if the library has already been loaded. It just checks load-history. It takes time only if the library has not yet been loaded, by loading the library. It all depends on what behavior you want. As I said, if you want to actually make sure the library is loaded when the sexp is evaluated then use a soft require. (If you want to load the library, and bind the key, at some later time, that's a different story.)
    – Drew
    Oct 4, 2020 at 18:14

1 Answer 1

1

You should use eval-after-load - the function will not be defined if the package is not loaded, so checking whether it's installed does not help and checking whether the function is defined (the fboundp stuff) will not load it.

BTW, ivy should be quoted in the eval-after-load call:

(eval-after-load 'ivy
    (global-set-key (kbd "C-x b") #'ivy-switch-buffer))

That's assuming that the function ivy-switch-buffer is defined in a file that provides the symbol ivy when loaded. That's usually the last thing done when loading a file: if you check ivy.el there should be a (provide 'ivy) at the bottom.

Alternatively, you can use a file name (in various forms) as argument:

(eval-after-load "ivy" ...)

Do C-h f eval-after-load RET and read the doc string for all the gory details.

EDIT: as the OP points out in a comment, package-installed-p works if you call it after calling package-intiialize: package-initialize loads the files in package-load-listso afterwards, checking whether the package is installed (i.e. it was in package-load-list) or whether it is loaded do the same thing. I still prefer eval-after-load because it will DTRT without extra conditions, but to each his/her own.

2
  • Seems that (package-installed-p 'ivy) works even if I haven't loaded module. To trigger eval-after-load I need to (ignore-errors (require ...)). I think eval-after-load vs package-installed-p are rivals and eval-after-load wins when package installed from Git, and package-installed-p wins after (package-initialize). Tnx!
    – gavenkoa
    Sep 30, 2020 at 14:14
  • 1
    (package-initialize) loads all the packages in package-load-list, so as long as you check afterwards, it should indeed work.
    – NickD
    Sep 30, 2020 at 14:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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