jwiegley / use-package

A use-package declaration for simplifying your .emacs
https://jwiegley.github.io/use-package
GNU General Public License v3.0
4.39k stars 259 forks source link

Installation of a list of packages automatically with use-package. #892

Closed hongyi-zhao closed 1 year ago

hongyi-zhao commented 3 years ago

The examples shown in installation guide are all the case of single package installation with one use-package instruction. But I want to install a list of packages automatically with use-package this way. Any hints for the corresponding lisp code?

Regards, HY

irigone commented 3 years ago

I don't know of such a feature built into use-package. I used straight with use-package before and being able to just (use-package firstpackage :straight t secondpackage) was very useful at least twice. When I changed everything to :ensure t use-package couldn't install anything and said that it wants one package instead of two. This feature can be very useful, for example when I installed yasnippet and yasnippet-snippets. The latter doesn't need any configuration, and even if it did it just makes a lot of sense to configure both in the same place. I stopped using straight because I'm too stupid to figure it out, but maybe you can use it.

hongyi-zhao commented 3 years ago

This feature can be very useful, for example when I installed yasnippet and yasnippet-snippets. The latter doesn't need any configuration, and even if it did it just makes a lot of sense to configure both in the same place.

I'm not so clear what you mean by saying the above.

I borrowed the following code snippets from here for this purpose:

(defvar prelude-packages
  '(s
    flycheck)
  "A list of packages to ensure are installed at launch.")

(defun prelude-packages-installed-p ()
  "Check if all packages in `prelude-packages' are installed."
  (cl-every #'package-installed-p prelude-packages))

(defun prelude-require-package (package)
  "Install PACKAGE unless already installed."
  (unless (memq package prelude-packages)
    (add-to-list 'prelude-packages package))
  (unless (package-installed-p package)
    (package-install package)))

(defun prelude-require-packages (packages)
  "Ensure PACKAGES are installed.
Missing packages are installed automatically."
  (mapc #'prelude-require-package packages))

(defun prelude-install-packages ()
  "Install all packages listed in `prelude-packages'."
  (unless (prelude-packages-installed-p)
    ;; check for new packages (package versions)
    (message "%s" "Emacs Prelude is now refreshing its package database...")
    (package-refresh-contents)
    (message "%s" " done.")
    ;; install the missing packages
    (prelude-require-packages prelude-packages)))

;; run package installation
(prelude-install-packages)
irigone commented 3 years ago

I'm not so clear what you mean by saying the above.

If I understood correctly, you want to install several packages in one use-package declaration. This is what I did before with straight.el. Sometimes, it's easier to read and understand several packages if they're in the same declaration. For example:

(use-package yasnippet
  :ensure t
  :init
  (yas-global-mode)
  :hook
  (yas-after-exit-snippet . indent-according-to-mode))

(use-package yasnippet-snippets
  :ensure t)

One is just an extension of the other and does not need any configuration. So why not put them under one configuration, like this?

(use-package yasnippet
  :ensure t yasnippet-snippets
  :init
  (yas-global-mode)
  :hook
  (yas-after-exit-snippet . indent-according-to-mode))
hongyi-zhao commented 3 years ago

But the suggested method in prelude project by bbatsov is a general way for all cases.

irigone commented 3 years ago

Ok :/

conao3 commented 3 years ago

leaf's :ensure can interpret multiple symbol. And your general way (using variable) works perfectly.

(setq leaf-expand-minimally t)
;;=> t

(macroexpand-1
 '(leaf *startup
    :ensure ace-window ag avy anzu))
;;=> (prog1 '*startup
;;     (leaf-handler-package *startup ace-window nil)
;;     (leaf-handler-package *startup ag nil)
;;     (leaf-handler-package *startup avy nil)
;;     (leaf-handler-package *startup anzu nil))

;; leaf-handler-package just check package is installed and install if the package missing.

(defvar prelude-packages
  '(ace-window
    ag
    avy
    anzu)
  "A list of packages to ensure are installed at launch.")
;;=> prelude-packages

(macroexpand-1
 '(leaf *starup
    :ensure `,prelude-packages))
;;=> (prog1 '*starup
;;     (leaf-handler-package *starup ace-window nil)
;;     (leaf-handler-package *starup ag nil)
;;     (leaf-handler-package *starup avy nil)
;;     (leaf-handler-package *starup anzu nil))
irigone commented 3 years ago

Honestly I started using straight and it does just what I wanted it to do

conao3 commented 3 years ago

good.

skangas commented 1 year ago

I think this is a duplicate of #718. There, I suggested using something like:

(defvar my-packages '(auto-compile
                       better-defaults
                       smex
                       fiplr
                       discover
                       yafolding
                       helm
                       org))
(dolist (p my-packages)
  (funcall use-package-ensure-function p))

I'm therefore closing this issue as a duplicate.