패키지 이름 목록을 지정하여 Emacs 패키지를 자동으로 설치하는 방법은 무엇입니까?


123

packageEmacs 확장을 관리하기 위해 사용 하고 있습니다. 다른 컴퓨터에서 내 Emacs 설정을 동기화하기 위해 .emacs파일 에 패키지 이름 목록을 지정한 다음 package패키지를 자동으로 검색하고 설치할 수 있는 방법을 원합니다. 그러면 을 호출하여 수동으로 설치할 필요가 없습니다 M-x package-list-packages. 그렇게하는 방법?


6
패키지 관리자를 사용하여 구성을 설치하는 경우 정확한 버전을 지정하고 싶을 것입니다 (가능하지 않은 경우 버전 관리에 모든 것을 직접 저장하는 것이 좋습니다). 그렇지 않으면 라이브러리가 업데이트되고 시작될 때 보호되지 않습니다. 갈등.
phils

답변:


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 2014

변수로서의 심볼 값은 void : package-archive-contents. Vundle for Vim과 같이 .emacs로 목록을 만들고 그 안에 정의 된 함수를 사용하여 목록의 모든 패키지 (설치된 경우 건너 뛰기, 오래된 경우 업데이트)를 설치할 수있는 방법이 있습니까? elpa /의 모든 패키지를 github로 푸시하고 싶지 않기 때문에 .NET에서 패키지가 업데이트 될 때마다이를 수행해야합니다 package.
CodyChan 2014 년

@rfinz는 무엇을 의미합니까? package-refresh-contents패키지가 설치되지 않은 경우에만 실행되는 것 같습니다 . 어떻게 (or (file-exists-p package-user-dir))더 나은 / 패키지가 설치되어있는 경우 어떻게조차 확인합니까?
Startec

@Startec 네 맞습니다! 사용자의 패키지 디렉토리가 존재하는지 여부를 확인하고 그렇지 않은 경우 실행 package-refresh-contents합니다. 이것은 아마도 새 컴퓨터에서 emacs를 처음 열 때만 실행될 것입니다. 패키지에 업데이트가 필요한 경우 수동으로 수행 할 수 있습니다.
rfinz

2
이미을 사용중인 경우 키워드를 use-package사용하여 :ensure패키지를 자동으로 설치할 수 있습니다 . package-selected-packages사용자 지정을 통해 또는 프로그래밍 방식으로 패키지 목록에 액세스해야하는 경우 에도 설정됩니다 .
Nick McCurdy

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

1
음, mapc부작용입니다. 하지만 왜 사용하지 unless않습니까?
Profpatsch

이전에이 코드를 사용했는데 "패키지 blah-blah를 설치할 수 없습니다"라는 알 수없는 이유로 작동하지 않는 경우가 있습니다 (여기서 blah-blah는 항상 목록의 첫 번째 요소입니다). 첫 번째 패키지를 수동으로 설치하면 모든 것이 잘 작동하지만 해결책은 아닙니다. 어쨌든 Nicolas Dudebois의 답변은 잘 작동합니다.
avp

내가 필요한 (package-initialize)기준에 전에package-user-dir
프랭크 Henard

3
그렇다면 설치하려는 패키지를 실제로 어디에 나열합니까?
Andriy Drozdyuk 2014

41

Emacs 25.1+는 사용자 정의 가능한 package-selected-packages변수 에서 사용자가 설치 한 패키지를 자동으로 추적 합니다. package-install사용자 정의 변수를 업데이트하고 package-install-selected-packages함수를 사용하여 선택한 모든 패키지를 설치할 수 있습니다 .

이 접근 방식의 또 다른 편리한 이점은에 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를 통해 설치되어 있어야합니다.이 크게 시작 속도를 느리게하는 것처럼 패키지 데시벨은 (마다 새로 고쳐지지 않습니다 )-제거 된 패키지가있는 경우에만.


귀하의 답변에 따라 약간 수정하고 'loop'사용을 제거했습니다. github.com/slipset/emacs/blob/master/ensure-packages.el
slipset

예,이 예는 필요 이상으로 정말 복잡합니다. 현재 Prelude에서 사용하는 코드는 훨씬 간단합니다.
Bozhidar Batsov 2013

7

아직 Cask에 대해 언급 한 사람은 없지만이 작업에 매우 적합합니다.

기본적으로 ~/.emacs.d/Cask설치하려는 패키지 목록 을 작성 합니다. 예를 들면 :

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

cask명령 줄에서 실행 하면 이러한 패키지와 필요한 종속성이 설치됩니다.

또한를 사용하여 설치된 패키지를 자동으로 업데이트 할 수 있습니다 cask update.


나는 얼마 동안 내 dotfile 에서 cask를 사용해 왔으며 훌륭하게 작동합니다.
Alastair 2014 년

유감스러운 Cask에는 Python이 필요한 것 같습니다. elisp 전용 대안이 있는지 궁금합니다. (즉, 패키지에서의,이 페이지를 만나 elisp 요구 사항에 분명히 대답.)
피터 Jaric

1
파이썬 스크립트는 cask-cli.el을 둘러싼 얇은 래퍼입니다. 원하는 경우 직접 호출 할 수 있습니다./path/to/emacs -Q --script /path/to/cask/cask-cli.el -- [args]
Alastair

흥미 롭군요! Emacs 내부에서 사용할 수 없습니까? 나는 그것이 또한 개발 도구이기 때문이라고 생각하지만, Emacs를 관리하기 위해 Emacs 외부에서 CLI로 이동해야하는 것은 다소 드문 일입니다.
Peter Jaric 2015-06-05

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? .NET Framework에 마멀레이드 또는 멜파를 추가해야한다고 생각합니다 package-archives. 그렇다면 실행할 수 (package-install 'dired+)있습니까?
ataylor

이 경우 (package-installed-p 'dired+)반환해야 t하며 위 코드에서 건너 뜁니다.
ataylor

package-installed-p혼자 잘 작동하지만, 코드의 전체 블록은하지 않습니다. 여러 패키지를 시도했습니다.
RNA

2
Nicolas Dudebout의 대답의 전주곡이 그것을 해결할 것 같습니다.
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

이 답변 에서 수행 한 것처럼 사용자가 먼저 패키지를 설치 하려는지 확인하는 것을 좋아 합니다. 또한 설치하기 전에 패키지 내용을 한 번 새로 고칩니다. 이것이 최선의 방법인지 확실하지 않지만 최고의 답변이 나를 위해 해주고 있다고 생각하지 않습니다.

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