パッケージ名のリストを指定してEmacsパッケージを自動的にインストールする方法は?


123

packageEmacs拡張機能の管理に使用しています。異なるコンピューターでEmacs設定を同期するために、.emacsファイルにパッケージ名のリストを指定し、パッケージをpackage自動的に検索してインストールできるようにしたいので、を呼び出して手動でインストールする必要はありませんM-x package-list-packages。どうやってするか?


6
パッケージマネージャーを使用して構成をインストールする場合は、正確なバージョンを指定することをお勧めします(それができない場合は、自分ですべてをバージョン管理に保存することを検討してください)。対立する。
phils 2012

回答:


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
私は好む:(または(file-exists-p package-user-dir)(package-refresh-contents))受け入れられた答えから。ここでパッケージを更新すると、すでにパッケージがインストールされているシステムでの起動時間が長くなります。この答えの残りは完璧です。
rfinz 14

変数としてのシンボルの値は無効です:package-archive-contents。Vundle for Vimのように、.emacsでリストを作成し、その中に定義されている関数を使用して、リスト内のすべてのパッケージをインストールする方法(インストールされている場合はスキップ、古い場合は更新)はありますか?elpa /のすべてのパッケージをgithubにプッシュしたくないので、パッケージがで更新されるたびに実行する必要がありますpackage
CodyChan 2014年

@rfinzはどういう意味ですか?package-refresh-contentsパッケージがインストールされていない場合にのみ実行されるように見えますか?どのように(or (file-exists-p package-user-dir))より良い/パッケージがインストールされている場合はどのようにそれもチェックしていますか?
Startec 2016

@Startecはい、あなたは正しいです!ユーザーのパッケージディレクトリが存在するかどうかを確認し、存在しない場合は実行しpackage-refresh-contentsます。これはおそらく、新しいコンピュータで初めてemacsを開いたときにのみ実行されますが、問題はありません。パッケージを更新する必要がある場合は、手動で実行できます。
rfinz

2
を既に使用use-packageしている場合は、:ensureキーワードを使用してパッケージを自動的にインストールできます。これはpackage-selected-packages、カスタマイズまたはプログラムによってパッケージリストにアクセスする必要がある場合にも設定します。
Nick McCurdy 2017

45

Profpatschによるコメントと以下の回答に基づく:

(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
それは…副作用のある地図ですか?そしての怠惰の誤用or?ああすごい。
Profpatsch 2013

1
まあ、mapc副作用のためです。しかし、なぜ使用しないのunlessですか?
Profpatsch 2013

以前、私はこのコードを使用しましたが、「パッケージblah-blahはインストールに利用できません」(ここではblah-blahは常にリストの最初の要素です)と言って、何らかの未知の理由で機能しませんでした。最初のパッケージを手動でインストールすると、すべてが正常に動作しますが、解決策ではありません。とにかく、ニコラス・デュドボワからの答えはうまくいきます。
avp

(package-initialize)参照する前に必要でしたpackage-user-dir
フランクヘナード2014年

3
では、実際にインストールしたいパッケージをどこにリストするのでしょうか?
Andriy Drozdyuk 2014

41

Emacs 25.1+は、カスタマイズ可能なpackage-selected-packages変数でユーザーがインストールしたパッケージを自動的に追跡します。package-installカスタマイズ変数が更新され、package-install-selected-packages関数を使用して選択したすべてのパッケージをインストールできます。

このアプローチのもう1つの便利な利点は、にpackage-autoremove含まれていないパッケージを自動的に削除できることですpackage-selected-packages(ただし、依存関係は保持されます)。

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

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


17

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)

あなたがMELPAを使用していない場合、あなたはそれを必要とする必要はありません(とあなたがしなければmelpa.el持っている上にあるように、あなたload-path(または)MELPA経由でインストールされています。これはかなり起動が遅くなり、パッケージDBは(たびに更新されていません)-アンインストールされたパッケージが存在する場合のみ。


あなたの答えに基づいて、私は少し修正し、「ループ」の使用を削除しましたgithub.com/slipset/emacs/blob/master/ensure-packages.el
スリップセット

ええ、この例は必要以上に本当に複雑です。私が現在Preludeで使用しているコードははるかに単純です。
Bozhidar Batsov 2013年

7

Caskについてはまだ誰も触れていませんが、このタスクには非常に適しています。

基本的には~/.emacs.d/Cask、インストールするパッケージのリストを作成します。例えば:

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

caskコマンドラインから実行すると、これらのパッケージと、必要な依存関係がインストールされます。

また、を使用してインストール済みパッケージを自動的に更新することもできますcask update


私はドットファイルでしばらくキャスクを使用していますが、うまくいきます。
Alastair 2014年

残念なことに、CaskはPythonを必要とするようです。elispのみの代替案はあるのでしょうか。(これはパッケージに含まれています。明らかにこのページの回答はelisp要件を満たしています。)
Peter Jaric

1
:Pythonスクリプトは、あなたのような場合は、直接呼び出すことができ樽-cli.el薄いラッパです/path/to/emacs -Q --script /path/to/cask/cask-cli.el -- [args]
アラステア

面白い!Emacs内からは使えませんか?それは開発ツールでもあるからだと思いますが、Emacsを管理するためにEmacsの外に出てCLIにアクセスする必要があるのは、ちょっと珍しいことです。
Peter Jaric

4

package-installパッケージ名をシンボルとして呼び出します。package-install対話的に呼び出して名前を完成させることにより、パッケージのパッケージ名を見つけることができます。この関数package-installed-pは、すでにインストールされているかどうかを通知します。

例えば:

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

1
おかげで、エラーが発生しましたerror: Package dired + 'はインストールできません `。dired +は私があなたのコードで試したパッケージです。
RNA

dired+あなたが実行したときに表示package-list-packages?マーマレードまたはメルパをに追加する必要があると思いますpackage-archives。もしそうなら、あなたは走ることができます(package-install 'dired+)か?
テイラー

その場合、(package-installed-p 'dired+)戻りtます。上記のコードではスキップされます。
テイラー

package-installed-p一人ではうまく動作しますが、コードのブロック全体にはありません。私はいくつかのパッケージを試しました。
RNA、

2
Nicolas Dudeboutの回答の前奏曲がそれを解決するようです。
テイラー

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

この回答のように、ユーザーが最初にパッケージをインストールするかどうかを確認するのが好きです。また、何かをインストールする前に、パッケージの内容を1回更新しています。これが最善の方法かどうかはわかりませんが、上位の回答が私のためにやっているとは思いません。

(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

に追加(package-install 'org)しても何も起こらないという問題に遭遇しました.emacs。の最新バージョンをインストールしたかっorg-modeたのorg-modeですが、組み込みはかなり古いです。

package-installEmacs 25.3.1からのソースコードを掘り下げました。関数selfはすでにパッケージがインストールされているかどうかをチェックし、パッケージがすでにインストールされている場合はインストールを拒否します。したがって、(unless (package-installed-p package) ...)回答10093312からのチェックは実際には要求されていません

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

組み込みorg-modeもインストール済みとしてカウントされ、package-installELPAからの新しいバージョンのインストールを拒否します。package.elを読んだ後、次の解決策を思いつきました。

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

それがpackage-*機能する理由は、それがシンボルであるかpackage-descオブジェクトであるかどうかに基づいて、ファミリ関数が引数を異なる方法で処理するためです。オブジェクトをpackage-install介してのみバージョン情報を指定できpackage-descます。


0

これは私のものです、それはより短いです:)

(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

ここに別の方法があります。

;; 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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.