web-dev-qa-db-fra.com

Comment installer automatiquement les paquets Emacs en spécifiant une liste de noms de paquets?

J'utilise package pour gérer mes extensions Emacs. Afin de synchroniser mes paramètres Emacs sur différents ordinateurs, je voudrais un moyen de spécifier une liste de noms de paquets dans .emacs fichier puis package peut rechercher et installer automatiquement les paquets, de sorte que je n'ai pas besoin de les installer manuellement en appelant M-x package-list-packages. Comment faire ça?

119
RNA

Basé sur les commentaires de Profpatsch et les réponses ci-dessous:

(defun ensure-package-installed (&rest packages)
  "Assure every package is installed, ask for installation if it’s not.

Return a list of installed packages or nil for every skipped package."
  (mapcar
   (lambda (package)
     ;; (package-installed-p 'evil)
     (if (package-installed-p package)
         nil
       (if (y-or-n-p (format "Package %s is missing. Install it? " package))
           (package-install package)
         package)))
   packages))

;; make sure to have downloaded archive description.
;; Or use package-archive-contents as suggested by Nicolas Dudebout
(or (file-exists-p package-user-dir)
    (package-refresh-contents))

(ensure-package-installed 'iedit 'magit) ;  --> (nil nil) if iedit and magit are already installed

;; activate installed packages
(package-initialize)
45
RNA
; list the packages you want
(setq package-list '(package1 package2))

; list the repositories containing them
(setq package-archives '(("elpa" . "http://tromey.com/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
                         ("marmalade" . "http://marmalade-repo.org/packages/")))

; activate all the packages (in particular autoloads)
(package-initialize)

; fetch the list of packages available 
(unless package-archive-contents
  (package-refresh-contents))

; install the missing packages
(dolist (package package-list)
  (unless (package-installed-p package)
    (package-install package)))
101
Nicolas Dudebout

Emacs 25.1+ gardera automatiquement une trace des paquets installés par l'utilisateur dans le fichier personnalisable package-selected-packages variable. package-install mettra à jour la variable de personnalisation et vous pourrez installer tous les packages sélectionnés avec le package-install-selected-packages une fonction.

Un autre avantage pratique de cette approche est que vous pouvez utiliser package-autoremove pour supprimer automatiquement les paquets qui ne sont pas inclus dans package-selected-packages _ (bien que cela préserve les dépendances).

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))
(package-install-selected-packages)

Source: http://endlessparentheses.com/new-in-in-package-el-in-emacs-25-1-user-selected-packages.html

38
Nick McCurdy

Voici le code que j'utilise pour Emacs Prelude :

(require 'package)
(require 'melpa)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

(setq url-http-attempt-keepalives nil)

(defvar prelude-packages
  '(ack-and-a-half auctex clojure-mode coffee-mode deft expand-region
                   Gist haml-mode haskell-mode helm helm-projectile inf-Ruby
                   magit magithub markdown-mode paredit projectile
                   python sass-mode Rainbow-mode scss-mode solarized-theme
                   volatile-highlights yaml-mode yari yasnippet zenburn-theme)
  "A list of packages to ensure are installed at launch.")

(defun prelude-packages-installed-p ()
  (loop for p in prelude-packages
        when (not (package-installed-p p)) do (return nil)
        finally (return t)))

(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
  (dolist (p prelude-packages)
    (when (not (package-installed-p p))
      (package-install p))))

(provide 'prelude-packages)

Si vous n'utilisez pas MELPA, vous n'avez pas besoin de l'exiger (et si vous utilisez melpa.el doit être sur votre load-path (ou installé via MELPA). La base de données des packages n'est pas actualisée à chaque fois (car cela ralentirait considérablement le démarrage) - uniquement si des packages désinstallés sont présents.

17
Bozhidar Batsov

Personne n'a encore mentionné Cask , mais cela convient tout à fait à cette tâche.

Fondamentalement, vous créez ~/.emacs.d/Cask listant les paquets que vous voulez installer. Par exemple:

(source melpa)
(depends-on "expand-region")
(depends-on "goto-last-change")
; ... etc

L'exécution de cask à partir de la ligne de commande installera ces packages pour vous, ainsi que toutes les dépendances dont ils ont besoin.

De plus, vous pouvez mettre à jour automatiquement les paquets installés en utilisant cask update.

7
Alastair
(require 'cl)
(require 'package)

(setq cfg-var:packages '(
       emmet-mode
       ergoemacs-mode
       flycheck
       flycheck-pyflakes
       monokai-theme
       py-autopep8
       py-isort
       Rainbow-mode
       yafolding
       yasnippet))

(defun cfg:install-packages ()
    (let ((pkgs (remove-if #'package-installed-p cfg-var:packages)))
        (when pkgs
            (message "%s" "Emacs refresh packages database...")
            (package-refresh-contents)
            (message "%s" " done.")
            (dolist (p cfg-var:packages)
                (package-install p)))))

(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
(package-initialize)

(cfg:install-packages)
4
Dunaevsky Maxim

Appel package-install avec le nom du paquet comme symbole. Vous pouvez trouver les noms de paquet pour vos paquets en appelant package-install de manière interactive et en complétant le nom. La fonction package-installed-p vous indiquera s’il a déjà été installé.

Par exemple:

(mapc
 (lambda (package)
   (or (package-installed-p package)
       (package-install package)))
 '(package1 package2 package3))
4
ataylor

J'aime vérifier si l'utilisateur veut installer les paquets d'abord comme cela est fait dans cette réponse . De plus, j'actualise le contenu de mon paquet une fois avant d'installer quoi que ce soit. Je ne suis pas sûr que ce soit la meilleure façon, mais je ne pense pas que les meilleures réponses le firent pour moi.

(setq required-pkgs '(jedi flycheck cider clojure-mode paredit markdown-mode jsx-mode company))

(require 'cl)

(setq pkgs-to-install
      (let ((uninstalled-pkgs (remove-if 'package-installed-p required-pkgs)))
        (remove-if-not '(lambda (pkg) (y-or-n-p (format "Package %s is missing. Install it? " pkg))) uninstalled-pkgs)))

(when (> (length pkgs-to-install) 0)
  (package-refresh-contents)
  (dolist (pkg pkgs-to-install)
    (package-install pkg)))
3
Frank Henard

Je me suis heurté à un problème: rien ne s'est passé après avoir ajouté (package-install 'org) Dans .emacs. Je voulais installer la version à jour de org-mode Et la fonction intégrée org-mode Est assez ancienne.

J'ai extrait le code source de package-install À partir d'Emacs 25.3.1. La fonction self vérifie déjà si un paquet est installé ou non et refuse de l'installer si le paquet est déjà installé. Donc, la vérification (unless (package-installed-p package) ...) De la réponse 10093312 est en fait injustifiée.

(defun package-install (pkg &optional dont-select)
  "Install the package PKG.
PKG can be a package-desc or a symbol naming one of the available packages
in an archive in `package-archives'.  Interactively, Prompt for its name.

If called interactively or if DONT-SELECT nil, add PKG to
`package-selected-packages'.

If PKG is a package-desc and it is already installed, don't try
to install it but still mark it as selected."
  (interactive
   (progn
     ;; Initialize the package system to get the list of package
     ;; symbols for completion.
     (unless package--initialized
       (package-initialize t))
     (unless package-archive-contents
       (package-refresh-contents))
     (list (intern (completing-read
                    "Install package: "
                    (delq nil
                          (mapcar (lambda (elt)
                                    (unless (package-installed-p (car elt))
                                      (symbol-name (car elt))))
                                  package-archive-contents))
                    nil t))
           nil)))
  (add-hook 'post-command-hook #'package-menu--post-refresh)
  (let ((name (if (package-desc-p pkg)
                  (package-desc-name pkg)
                pkg)))
    (unless (or dont-select (package--user-selected-p name))
      (package--save-selected-packages
       (cons name package-selected-packages)))
    (if-let ((transaction
              (if (package-desc-p pkg)
                  (unless (package-installed-p pkg)
                    (package-compute-transaction (list pkg)
                                                 (package-desc-reqs pkg)))
                (package-compute-transaction () (list (list pkg))))))
        (package-download-transaction transaction)
      (message "`%s' is already installed" name))))

Le paramètre org-mode Intégré compte également comme installé et package-install Refuse d'installer la nouvelle version à partir d'ELPA. Après avoir passé du temps à lire package.el, j’ai trouvé la solution suivante.

(dolist (package (package-compute-transaction
                  () (list (list 'python '(0 25 1))
                           (list 'org '(20171211)))))
  ;; package-download-transaction may be more suitable here and
  ;; I don't have time to check it
  (package-install package))

La raison pour laquelle cela fonctionne est que les fonctions de la famille package-* Traitent les arguments différemment selon qu’il s’agit d’un symbole ou d’un objet package-desc. Vous pouvez uniquement spécifier les informations de version pour package-install Via un objet package-desc.

1
Lei Zhao

Voici le mien, c'est plus court :)

(mapc
 (lambda (package)
   (unless (package-installed-p package)
     (progn (message "installing %s" package)
            (package-refresh-contents)
            (package-install package))))
 '(browse-kill-ring flycheck less-css-mode tabbar org auto-complete undo-tree clojure-mode markdown-mode yasnippet paredit paredit-menu php-mode haml-mode Rainbow-mode fontawesome))
0
yPhil