在Emacs中更新软件包

177
我有以下的包设置(不确定是否有更好的推荐):
(require 'package)
(setq package-archives '(("ELPA" . "http://tromey.com/elpa/") 
                          ("gnu" . "http://elpa.gnu.org/packages/")
                          ("marmalade" . "http://marmalade-repo.org/packages/")))

; Apparently needed for the package auto-complete (why?)
(add-to-list 'package-archives
             '("melpa" . "http://melpa.milkbox.net/packages/") t)

(package-initialize)
(setq url-http-attempt-keepalives nil)

我有三个与软件包安装和更新相关的问题。

问题1:是否有一种方法可以更新可用软件包列表(以及最新版本)并更新特定软件包?

问题2:以下软件包源之间有什么区别?:

  • ELPA,
  • GNU
  • marmalade
  • melpa

问题3:将它们添加到package-archives中的顺序是否重要?


14
显然,由于没有人想在Marmalade上提供auto-complete,因此需要使用MELPA。 不要费心,而是清理您的“package-archives”。 摆脱不再维护的ELPA存档以及混乱、过时和重复包缺乏明确指导和维护的marmalade存档。 只使用标准的GNU存档和MELPA。 - user355252
2
谢谢@lunaryorn!这非常有帮助。您知道我如何保持对此类事物的了解吗?(即像Emacs这样发展时需要知道的“好东西”) - Amelio Vazquez-Reina
3
信息在网络中自由流动,只需要抓住它:在 Reddit 上关注 /emacs,关注像 Nic Ferrier、Bozhidar Batsov、Magnar Sveen、John Wiegley 等著名 Emacs 人士的博客和 Twitter,加入 Freenode IRC 上的 #emacs 频道等等。 - user355252
4
如果您打算手动调用(package-initialize),则应该将(setq package-enable-at-startup nil)加入到配置中以避免错误。 - phils
2
感谢@phils - 为什么需要这个? - Amelio Vazquez-Reina
显示剩余2条评论
4个回答

190
为了自动更新软件包列表,仅当没有软件包列表时,请使用以下代码:
```lisp (when (not package-archive-contents) (package-refresh-contents)) ```
要更新所有已安装的软件包,请键入`package-list-packages`,这将带您进入`*Packages*`缓冲区(同时也会更新软件包列表),然后键入`U x`。
`package-refresh-contents`无条件地尝试从您添加到`package-archives`的所有仓库下载软件包列表;如果您已经下载了软件包列表,则`package-archive-contents`为非空。 ELPA是最初的版本。我认为它已经不再维护了,但我不确定。我不使用它。 GNU是“官方”的。它与Emacs一起维护,这意味着它应该始终正常工作,但更新和新软件包并不频繁。 Marmalade基本上是一个网站,您可以在其中上传一个完整的软件包,然后它将被添加到Marmalade仓库。您不仅仅提交软件包的上游链接,它也不完全自动化软件包的创建。我认为这是正确的做法,因为您不一定想要跟踪上游。不幸的是,它已经有一段时间没有维护了,但最近有人接手了,所以它应该会在某个时候回来并变得更好。 Melpa接受一个URL,例如EmacsWiki的lisp区域或github仓库,并从中自动构建一个软件包。因此,它通常比它跟踪的内容晚一天。尽管它跟踪上游,但我在实践中从未遇到过问题,这也是我大部分软件包的来源。还有Melpa Stable,它类似于Melpa,但是获取上游仓库的标记版本而不是最新版本。Melpa Stable的软件包比Melpa少。可能应该优先选择Melpa而不是Melpa Stable。 Org mode有自己的package.el仓库(http://orgmode.org/elpa/)。
所有软件包仓库的工作方式都相同,只需将它们添加到您的package-archives中。
这是一个更详细的博文,关于这个主题,我基本上同意其中的观点。
我不确定,但我认为如果一个软件包在不同的仓库中重复出现,那么在package-archives中的仓库出现的顺序决定了优先级。我不知道较高的优先级是在列表的开始还是结束。
更新:在Emacs 25中,有一个名为package-archive-priorities的变量,您可以使用它来优先处理您的软件包仓库(例如,优先使用ELPA而不是MELPA)。
这是我init.el的相关部分,如果你感兴趣的话。
(setq jpk-packages
      '(
        ac-dabbrev
        ...
        yasnippet
        ))

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

;; install any packages in jpk-packages, if they are not installed already
(let ((refreshed nil))
  (when (not package-archive-contents)
    (package-refresh-contents)
    (setq refreshed t))
  (dolist (pkg jpk-packages)
    (when (and (not (package-installed-p pkg))
             (assoc pkg package-archive-contents))
      (unless refreshed
        (package-refresh-contents)
        (setq refreshed t))
      (package-install pkg))))

(defun package-list-unaccounted-packages ()
  "Like `package-list-packages', but shows only the packages that
  are installed and are not in `jpk-packages'.  Useful for
  cleaning out unwanted packages."
  (interactive)
  (package-show-package-list
   (remove-if-not (lambda (x) (and (not (memq x jpk-packages))
                            (not (package-built-in-p x))
                            (package-installed-p x)))
                  (mapcar 'car package-archive-contents))))

2
谢谢!when (not package-archive-contents) 检查什么? - Amelio Vazquez-Reina
3
这个条件语句可以防止每次启动emacs时都进行刷新(通常我只希望在我要求它检查时才这样做)。它仅在没有软件包存档的情况下进行检查,这种情况应该只会在我第一次将我的配置克隆到新机器上时出现。 - jpkotta
只是让您知道@Brandy Trainor的答案,它似乎补充了您的答案 - 如果有帮助的话。 - Amelio Vazquez-Reina
1
@alper U 运行 package-menu-mark-upgrades,而 x 运行 package-menu-execute。你应该能够自动运行它们(可能需要使用 with-current-buffer 或类似的命令确保你在 *Packages* 缓冲区中)。虽然我不建议这样做,因为升级可能会破坏一些东西,我宁愿留出一些时间来有意识地进行升级,以确保升级成功。 - jpkotta
https://www.reddit.com/r/emacs/comments/etikbz/speaking_as_a_package_maintainer_please_do_not/ 建议不要使用MELPA Stable。我不得不说我同意这个观点;我就是其中一个因为错误的假设而受到影响的用户之一。 - undefined
显示剩余5条评论

123
在Emacs中,使用M-x list-packages列出所有包,它们将自动刷新存档内容。然后使用U标记所有可升级的包进行升级,使用x实际执行新的更新。Emacs将获取并安装所有升级,并询问您是否要删除旧的、过时的版本。
您还可以查看Carton,它提供了一种更方便的方式来管理您的包,通过在专用文件中声明它们,并包括一个方便的命令行客户端,以自动安装和升级以这种方式声明的包。

package-archives 的顺序并不重要。Emacs 会将所有库的内容汇总到一个可用软件包及其版本的单一连贯列表中,该列表存储在 package-archive-contents 中。

在执行 package-install 时,Emacs 将简单地选择最新版本的软件包,而不考虑其来源库。对于更多关于软件包来源的控制,MELPA 提供了 melpa package,允许从指定的库中黑名单或白名单软件包。


6
更准确地说,那是“S-u”。 - Lenar Hoyt
2
我的意思是“Shift-u”。 - Lenar Hoyt
9
@mcb 嗯,这就是为什么我写了一个大写的U。 - user355252
1
这只是为像我一样困惑的人而设计的,他们认为这意味着<kbd>U</kbd>。 - Lenar Hoyt
1
顺便提一下,“S-”代表“超级键” https://www.gnu.org/software/emacs/manual/html_node/emacs/Modifier-Keys.html - ecarlin
显示剩余2条评论

48

在终端中:

emacs

M-x list-packages

这将把您置于“packages”缓冲区中

shift-u x

emacs会问你(y/n),等待更新。

C-x k <ret>

这将清除 *packages* 缓冲区并将您返回到 *scratch*

C-x-C-c

这将退出emacs,并让您通过重新启动,但您可能需要进行调试 :(

emacs

我的见解


当我输入“U”时,出现了“未指定命令”的提示。在运行M-x package-refresh-contents之后,它提示我输入“U”以标记所有更新,然后我才能输入“x”来运行更新。 - MrColes
1
当Emacs守护程序启动时,这个操作可以自动完成吗? - alper
server-mode-hook允许您在进入或离开server-mode时运行任意函数。或者,您可以使用defadviceserver-start周围运行函数。如果您无法从这些提示中弄清楚,请另外提出一个问题。 - undefined

2

这是对jpkotta答案的进一步评论。

我正在尝试调整jpkotta上面的答案:

(setq n 0)                                  ; set n as 0
(dolist (pkg pkgs-2b-present)               ; for each pkg in list
  (unless (or                               ; unless
           (package-installed-p pkg)        ; pkg is installed or
           (assoc pkg                       ; pkg is in the archive list
                  package-archive-contents))
    (setq n (+ n 1))))                      ; add one to n
(when (> n 0)                               ; if n > 0, 
  (package-refresh-contents))               ; refresh packages

替换代码(when (not package-archive-contents) (package-refresh-contents))

对于我的使用情况来说,软件包列表没有足够的刷新频率。

我还没有考虑是否有更有效的解决方案;首先,我需要看看这个调整是否能解决问题。


在我的回答中,只有在package-archive-contents不存在时才会刷新。这个想法是你将你的.emacs.d复制到一个新的机器上,它会自动安装所有的包,但之后你必须手动更新。我尝试每两周更新一次。我猜你添加了一个包到你的列表中,但是你的package-archive-contents太旧了,没有包含它? - jpkotta
@jpkotta,我有一个双启动系统,每个系统都使用它们默认的~/.emacs.d/elpa/作为包的位置。然而,我安装你的包的代码版本在“第三个”分区中(e:/emacs-config/e/emacs-config/)。所以我在一个操作系统中添加了一个包到列表中,在另一个操作系统中加载Emacs时应该会更新。当然,我的解决方案可能有些过度设计,但至少它似乎是有效的。 - Brady Trainor
@jpkotta,为什么我的package-archive-contents似乎如此混乱,这个问题我并没有找到答案。如果将来我找到了“更优雅”的解决方案,我会在我的帖子中添加它。 - Brady Trainor
1
(package-refresh-contents)会写入~/.emacs.d/elpa/archives。不清楚您是否在操作系统之间共享了该目录。我建议不要共享elpa/目录,因为Emacs字节码(elpa/中的代码是字节编译的)不向后兼容(http://www.gnu.org/software/emacs/manual/html_node/elisp/Byte-Compilation.html)。您必须确保两个安装都具有相同版本的Emacs。我将我的`.emacs.d`保存在版本控制中,并使用它来同步不同的安装。 - jpkotta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接