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?
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)
; 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)))
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
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.
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
.
(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)
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))
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)))
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
.
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))