「GNU Emacs」- 包管理系统(ELPA, Emacs Lisp Package Archive) @20210309
ELPA & package.el
ELPA(Emacs Lisp Package Archive)是 Emacs 的扩展仓库,从 GNU Emacs 24 开始引入。还有很多其他非官方仓库,比如 GnuELPA、Marmalade,以及我们用的最多的 MELPA 仓库。
package.el 是 Emacs 的扩展管理器(实际上是“库”(lib)),包含很多用于管理扩展的函数及命令,可以从 ELPA 中下载扩展、安装扩展,同时也支持搜索、管理等等功能,目的是简化 Emacs 扩展的安装。
配置及使用
第一步、配置扩展仓库
修改 .emacs 或者 ~/.emacs.d/init.el 文件,添加如下配置:
(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ;; GNU ELPA repository (Offical) ("melpa" . "https://melpa.org/packages/") ;; MELPA repository ("melpa-stable" . "https://stable.melpa.org/packages/") ;; MELPA Stable repository ("org" . "http://orgmode.org/elpa/"))) ;; Org-mode's repository
或者,使用 M-x customize-variable [RET] package-archives [RET] 进行配置:
1)Archive name: 填写仓库名,比如 gnu、melpa、melpa-stable 等等;
2)URL or directory name: 填写仓库地址,比如 https://melpa.org/packages/ 地址;
在完成仓库配置后,执行 M-x package-refresh-contents 指令,来创建扩展索引缓存(实际上是下载 archive-contents 文件,并进行处理,然后保存到 /.emacs.d/elpa/archives/<archive-name>/ 目录,该文件保存在某个仓库内全部的全部扩展、下载地址等等信息)。
第二步、安装插件(键盘操作)
1)Type M-x list-packages to open the package list.
2)Press ‘i’ to mark for installation, ‘u’ to unmark,
3)and ‘x’ to perform the installation.
4)Press ‘RET’ to read more about installing and using each package.
使用 ELPA 安装的插件,位于 $HOME/.emacs.d/elpa/ 目录。
其他常见操作
更新插件(键盘操作)
如下方法,将升级全部可升级的扩展:
0)更新缓存:M-x package-refresh-contents
1)查看扩展:M-x list-packages
2)标记升级:Then, press [U] to mark all upgradable packages to be upgraded.
3)执行升级:Last, press [x] to perform the new updates.
如果进需要更新_特定_扩展,重新安装(reinstall)即可:
1)更新缓存:M-x package-refresh-contents
2)更新扩展:M-x package-reinstall <package>
删除插件(键盘操作)
1)查看扩展:M-x package-list-packages
2)搜索扩展:C-s django-snippets
3)标记删除:Mark the package for deletion by typing ‘d’
4)执行删除:Execute by typing ‘x’
或者,使用 M-x package-delete RET "<package name>" 命令,直接删除扩展;
插件降级
如果,在升级后,出现插件功能异常或者其他问题,我们需要降级。这也是可以的,参考 ELPA policy 部分。
重新编译全部插件
M-: (byte-recompile-directory package-user-dir nil 'force) [RET]
扩展加载流程(原理简述)
Emacs start up => Load init file & abbrev file => (package-initialize) => `after-init-hook`
使用 (setq package-enable-at-startup nil) 指令,可以关闭扩展的自动加载。
因此,我们不应该在初始化文件(init.el)中进行扩展的初始化,因为,在执行初始化文件时,扩展还没有加载。
但是,以下几种操作是可行的:
1)可以修改用于扩展的自定义变量;
2)不依赖于扩展加载的 auto-mode-alist 修改:(add-to-list 'auto-mode-alist '("\\.gradle" . groovy-mode))
3)当扩展加载成功后执行的 Hook:(add-hook 'groovy-mode-hook (lambda () (setq tab-width 4)))
4)快捷键绑定;
5)某些扩展的初始化,在加载扩展前,可以使用 eval-after-load 完成设置;
6)可以指定 (package-initialize) 来尽早加载扩展,然后便可使用 (require) 引入扩展并进行设置;
7)如果上面的方法都存在问题,可以使用 (add-hook 'after-init-hook 'cycbuf-init) 进行处理;
常见问题汇总
执行 package-refresh-contents 失败,无法更新包缓存(未解决)
问题描述:在执行 package-refresh-contents 命令时,经常会出现如下几种错误:
... Failed to download ‘melpa’ archive. ... (wrong-type-argument stringp (require . china-util)) ... (wrong-type-argument stringp (require . info)) ...
问题原因:
# 09/12/2020 在使用 edebug 调试后,我们没有找到具体的原因。但是,有时候又能够正常更新,所以,我们猜测是网络原因导致响应内容被破坏而导致失败。
# 01/31/2021 在使用 mitmproxy 抓包后,我们发现响应内容没有问题。
# 03/03/2021 只要把 ~/.emcas 相关的配置移出(备份到其他目录,一切就恢复正常了)。我们又怀疑这个问题与 LC_CTYPE=zh_CN.UTF 环境变量有关。
# 03/04/2021 该错误会导致我们无法通过 Package 安装工具,这是最大的问题。但是,我们找到一个替代方案:
1)通过不加载配置,而仅使用自己的配置,来启动:emacs --no-init-file --load init-lite.el
2)而配置文件 init-lite.el 仅包含用于安装数据包的配置:
(setq url-proxy-services '(("http" . "127.0.0.1:8123") ("https" . "127.0.0.1:8123"))) (custom-set-variables '(package-archives '(("gnu" . "https://elpa.gnu.org/packages/") ("melpa" . "https://melpa.org/packages/"))))
3)在安装完成之后,我们再正常启动 emacs 应用即可(应用的安装实际就是下载应用到 ~/.emacs.d/elpa/<package-name>/)。
相关链接
EmacsWiki / ELPA
Milkypostman’s Emacs Lisp Package Archive
相关文章
「GNU Emacs」- 行号操作(显示、统计、定位)
「GNU Emacs」- 常用界面设置
「GNU Emacs」- 快速切换窗口(Window)
「GNU Emacs」- 常用 Frame 设置
「GNU Emacs」- 常用 Window 配置
参考文献
GNU Emacs Lisp Package Archive
Getting Started - MELPA Stable
EmacsWiki: InstallingPackages
emacs - How to remove installed elpa package - Stack Overflow
How to upgrade packages installed by ELPA in Emacs? - SysTutorials
How to easily update one elpa package? : emacs
use-package Tries To Load Outdated MELPA Package?
Emacs , use-package and package-refresh-contents
How to rebuild ELPA packages after upgrade of Emacs - Stack Overflow