There are many different solutions for the above two problems. The natural way of solving the first problem will be to maintain a list of packages that we use and check if those are installed. If some package is not installed, install it. Something like this:

(defvar my-packages '(spacemacs-theme company)) (dolist (p my-packages)

(when (not (package-installed-p p))

(package-install p)))

Note: In Elips any function ending with a -p is a predicate.

This solution works perfectly well.

But there is a very elegant solution for this (which happens to solve the second problem as well).

It is called use-package.

Use-package

use-package is an Elisp macro written by John Wiegley. It simplifies and groups together configuration for packages. Install use-package by pressing:

(By now, you should know how to install a package.)

M-x package-install <RET> use-package <RET>

A common use-package declaration looks like this:

(use-package <package-name>

:init

<code to be executed before loading the package> :config

<code to be executed after loading the package> :bind

<key bindings for this package>)

Note: Any word, preceded with a : is called a keyword in Elisp. You can consider keywords as being similar to strings, but with a different purpose and presence.

Let’s see how would a use-package declaration look for company . Our current config for company is:

(global-company-mode t) (define-key company-active-map (kbd "C-n") 'company-select-next)

(define-key company-active-map (kbd "C-p") 'company-select-previous) (setq company-idle-delay 0.0)

With use-package, it will look like this:

(use-package company

:bind (:map company-active-map

("C-n" . company-select-next)

("C-p" . company-select-previous))

:config

(setq company-idle-delay 0.3)

(global-company-mode t))

Here we are saying-

This is a use-package declaration for the package company . In company-active-map , bind C-n to company-select-next and C-p to company-select-previous .

Notice the minimal syntax here vs the define-key call. After company is loaded, set company-idle-delay to 0.3 and enable company mode everywhere.

Now all the configuration related to company is naturally grouped together in the use-package declaration. Next time when we want to make some changes to company , we will come to this declaration and add our code. This way, our setup will always be well grouped. So use-package has solved our second problem.

But what about the first problem? Will use-package download the missing packages?

Yes, it will. You just have to add :ensure t to the declaration. For example, look at this:

(use-package magit

:ensure t

:bind ("C-x g" . magit-status))

Note: Magit is an super awesome git client for Emacs that you must use.

:ensure t will make sure that magit is downloaded if it is not there. Also, look at the bind syntax here. When you want to make a global binding (unlike the bind in company , which was local to company-mode-map ), the syntax is even more minimal. You just have to specify (key-binding . command) pairs. :)

use-package has solved both of our problems! :)

Note: use-package has many more useful (and very well thought of) keywords. I recommend going through the README.md.

Note: Even though use-package is a handy macro, we must know what is going on under the hood when we use it. Since it is just a macro, you can expand it yourself and see what is going on. Read about macro expansion here.