Bir paket adları listesi belirterek Emacs paketleri otomatik olarak nasıl kurulur?


123

packageEmacs uzantılarımı yönetmek için kullanıyorum . Emacs ayarlarımı farklı bilgisayarlarda senkronize etmek için, .emacsdosyada bir paket adları listesi belirtmenin bir yolunu istiyorum ve ardından packagepaketleri otomatik olarak arayabilir ve kurabilirim, böylece onları arayarak manuel olarak yüklememe gerek kalmaz M-x package-list-packages. Bu nasıl yapılır?


6
Yapılandırmanızı yüklemek için paket yöneticisine güveniyorsanız, muhtemelen tam sürümleri belirtmek isteyeceksiniz (ve bu mümkün değilse, her şeyi sürüm kontrolünde saklamayı düşünün), aksi takdirde kitaplıklar güncellendiğinde ve başladığında korunmuyorsunuz çatışmaya.
phils

Yanıtlar:


107
; 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)))

7
Kabul edilen yanıttan (veya (dosya-var-p paket-kullanıcı-dir) (paket-yenileme-içeriği)) tercih ediyorum. Buradaki paket yenileme, paketlerin zaten kurulu olduğu sistemlerde başlatma süresini uzatır. Yine de bu cevabın geri kalanı mükemmel.
rfinz

Sembolün değişken olarak değeri void: paket arşiv içeriği. Vundle for Vim gibi .emacs'de bir liste oluşturup listedeki tüm paketleri kurmak için (eğer kuruluysa atla, eskiyse güncelle) içinde tanımlanan bir işlevi kullanabilmemin bir yolu var mı? Tüm paketleri elpa / github'a göndermek istemediğim için, bir paket her güncellendiğinde bunu yapmak zorundayım package.
CodyChan

@Rfinz ne demek? Görünüşe göre package-refresh-contentssadece paket kurulu değilse çalıştırılacak mı? Nasıl daha (or (file-exists-p package-user-dir))iyi / paketlerin kurulu olup olmadığını nasıl kontrol ediyor?
Startec

@Startec evet haklısın! Kullanıcının paket dizininin var olup olmadığını ve çalışıp çalışmadığını kontrol eder package-refresh-contents. Bu muhtemelen sadece yeni bir bilgisayarda emacs'i ilk açtığınızda çalıştırılacak ve bunda sorun yok. Bir paketin güncellenmesi gerekiyorsa, bu manuel olarak yapılabilir.
rfinz

2
Zaten kullanıyorsanız use-package, :ensurepaketleri otomatik olarak kurmak için anahtar kelimeyi kullanabilirsiniz . Bu package-selected-packages, paket listesine özelleştirme yoluyla veya programatik olarak erişmeniz gerekip gerekmediğini de ayarlar .
Nick McCurdy

45

Profpatsch tarafından yapılan yorumlara ve aşağıdaki cevaplara göre:

(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)

2
Bu… yan etkileri olan bir harita mı? Ve tembelliğini kötüye kullanmak or? Vay canına.
Profpatsch

1
Eh, mapcyan etkiler için. Ama neden kullanmıyorsun unless?
Profpatsch

Daha önce bu kodu kullandım ve bazen bilinmeyen bir nedenle "Paket blah-blah kurulum için mevcut değil" diyerek çalışmıyordu (burada blah-blah her zaman listenin ilk öğesidir). İlk paketi manuel olarak kurarsam, her şey yolunda gider, ancak bu bir çözüm değildir. Her neyse, Nicolas Dudebois'in cevabı gayet iyi çalışıyor.
avp

(package-initialize)Referanstan önce ihtiyacım vardıpackage-user-dir
Frank Henard

3
Peki, kurulmasını istediğimiz paketleri gerçekten nerede listeliyoruz?
Andriy Drozdyuk

41

Emacs 25.1+, özelleştirilebilir package-selected-packagesdeğişkende kullanıcı tarafından yüklenen paketleri otomatik olarak takip edecektir . package-installözelleştir değişkenini günceller ve seçilen tüm paketleri bu package-install-selected-packagesişlevle kurabilirsiniz .

Bu yaklaşımın bir başka kullanışlı avantajı, package-autoremovedahil edilmeyen paketleri otomatik olarak kaldırmak için kullanabilmenizdir package-selected-packages(bağımlılıkları koruyacak olsa da).

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

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


17

İşte Emacs Prelude için kullandığım kod :

(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)

MELPA kullanmıyorsanız, buna ihtiyaç duymanıza gerek yoktur (ve varsa melpa.el, cihazınızda load-path(veya MELPA aracılığıyla kurulursa) olması gerekiyorsa. Paket db her seferinde yenilenmez (bu, başlatmayı önemli ölçüde yavaşlatır. ) - yalnızca kaldırılmış paketlerin bulunduğu yerlerde.


Cevabınıza dayanarak, biraz değiştirdim ve 'döngü' kullanımını kaldırdım github.com/slipset/emacs/blob/master/ensure-packages.el
13:49

Evet, bu örnek olması gerekenden gerçekten daha karmaşık. Şu anda Prelude'da kullandığım kod çok daha basit.
Bozhidar Batsov

7

Henüz kimse Cask'tan bahsetmedi , ancak bu görev için oldukça uygun.

Temel olarak ~/.emacs.d/Cask, kurmak istediğiniz paketleri listelersiniz. Örneğin:

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

caskKomut satırından çalıştırmak , bu paketleri sizin için ve ihtiyaç duydukları tüm bağımlılıkları kuracaktır.

Ayrıca, yüklü paketleri kullanarak otomatik olarak güncelleyebilirsiniz cask update.


Bir süredir dot dosyalarımda cask kullanıyorum , harika çalışıyor.
Alastair

Yazık bir Cask, Python gerektiriyor gibi görünüyor. Sadece elisp için bir alternatif olup olmadığını merak ediyorum. (Bu bir paket içinde en; bu sayfayı buluştuğu elisp gereklilik üzerine besbelli cevapları.)
Peter Jaric

1
Python betiği, isterseniz doğrudan çağırabileceğiniz cask-cli.el etrafında ince bir sarmalayıcıdır:/path/to/emacs -Q --script /path/to/cask/cask-cli.el -- [args]
Alastair

İlginç! Emacs içinden kullanmak mümkün değil mi? Sanırım bunun nedeni aynı zamanda bir geliştirme aracı, ancak Emacs'ı yönetmek için Emacs dışında bir CLI'ye geçmek biraz alışılmadık bir durum.
Peter Jaric

4

package-installPaket ismini sembol olarak arayın . Paketlerinizin paket adlarını package-installinteraktif olarak arayarak ve adı doldurarak bulabilirsiniz. İşlev package-installed-p, önceden yüklenmiş olup olmadığını size bildirir.

Örneğin:

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

1
Teşekkürler, ancak error: Package + 'kurulum için uygun değil' şeklinde bir hata aldım . dired + kodunuzla denediğim bir paket.
RNA

Does dired+çalıştırdığınızda ortaya package-list-packages? İçinize marmelat veya melpa eklemeniz gerektiğine inanıyorum package-archives. Eğer öyleyse, koşabilir (package-install 'dired+)misin?
ataylor

Bu durumda, (package-installed-p 'dired+)geri dönmeli tve yukarıdaki kodda atlanacaktır.
ataylor

Tek package-installed-pbaşına iyi çalışıyor, ancak kod bloğunun tamamı çalışmıyor. Birkaç paket denedim.
RNA

2
Görünüşe göre Nicolas Dudebout'un cevabındaki başlangıç ​​bunu çözecek.
ataylor

4
(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)

3

Bu cevapta yapıldığı gibi kullanıcının paketleri ilk önce kurmak isteyip istemediğini kontrol etmeyi seviyorum . Ayrıca herhangi bir şey yüklemeden önce paket içeriğimi bir kez yenileyiyorum. Bunun en iyi yol olduğundan emin değilim, ama en iyi yanıtların bunu benim için yaptığını sanmıyorum.

(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)))

1

Ben hiçbir şey eklemeden sonra oldu o bir sorunla karşılaştık (package-install 'org)içine .emacs. Güncel sürümünü yüklemek istedim org-modeve yerleşik org-modeoldukça eski.

package-installEmacs 25.3.1'den kaynak kodunu çıkardım . Self işlevi, bir paketin kurulu olup olmadığını kontrol eder ve paket zaten kurulmuşsa yüklemeyi reddeder. Yani 10093312(unless (package-installed-p package) ...) numaralı cevabın kontrolü aslında gereksizdir .

(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))))

Yerleşik org-modeda sayımları gibi kurulmuş ve package-installELPA gelen yeni bir sürümünü yüklemeye reddeder. Package.el okumak için biraz zaman harcadıktan sonra, aşağıdaki çözümü buldum.

(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))

Çalışmasının nedeni, package-*aile işlevlerinin, bir sembol veya package-descnesne olmasına bağlı olarak argümanları farklı şekilde ele almasıdır. Yalnızca package-installbir package-descnesne aracılığıyla sürüm bilgisi belirtebilirsiniz .


0

İşte benim, daha kısa :)

(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

İşte başka bir yol.

;; assure every package is installed
(defun ensure-package-installed (&rest packages)
  (let ((user-required-packages
         (seq-remove
          (lambda (package) (package-installed-p package))
          packages)))
    (when user-required-packages
      (package-refresh-contents)
      (dolist (package user-required-packages)
        (package-install package)))))

;; list of packages to install
(ensure-package-installed
 'try
 'which-key)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.