使用 use-package vc 进行包安装
tags: use-package
文章目录
在上一篇文章里介绍了 Emacs 30 里, use-package
支持了 :vc
关键字,用于从版本管理工具里下载包,得益于 VC 的功能,Git/SVN 通通都支持。
用法也很简单:
(use-package bbdb
:vc (bbdb :url "https://git.savannah.nongnu.org/git/bbdb.git"
:lisp-dir "lisp"
:doc "doc/bbdb.texi"))
:vc
后面跟的是一个 alist,用来描述包信息,在上面示例中:
bbdb
包名,也是下载的目录名,通过 vc 下载的包也是在elpa
文件夹内其余的部分是个 plist,常用的属性有:
url
仓库地址lisp-dir
代码位置,默认是项目根目录rev
可以分支名、tag 名、commit id,特殊值:last-release
表示最新的 release 分支main-file
从这个文件中提取包的 metadata 信息,默认是包名.el
通过上面的 plist 我们就可以轻松的安装任意包的任意版本,不会再出现因为重新安装某个包,导致某些功能失效的问题。相比 submodule,vc 的方式有如下好处:
- 自动包安装依赖
- 自动生成 autoloads
但有一点不完美,vc clone 时是全部历史都下载,一些大型的项目可能会比较慢,目前还没很好解法,只能通过 advice 来兜底:
(defun my/vc-git-clone (fn remote directory rev)
(if (or (not (string-match-p "elpa" directory))
(null rev))
(funcall fn remote directory rev)
(cond
((ignore-errors
;; First try if rev is a branch/tag name
;; https://stackoverflow.com/a/48748567/2163429
(vc-git--out-ok "clone" "--depth" "1" "--single-branch" "--branch" rev remote directory)))
((vc-git--out-ok "clone" "--single-branch" remote directory)
(let ((default-directory directory))
(vc-git--out-ok "checkout" rev))))
directory))
(advice-add 'vc-git-clone :around
'my/vc-git-clone)
代码也比较简单直接,当判断下载的目录在 elpa 中,并且 rev 不为空时,尝试进行浅 clone,如果 rev 不是分支名或标签名,也有个 优化,就是只下载单个分支,然后再切到指定 commit 上。
目前我已经把十几个 submodule 换成了 vc 方式,效果非常不错,下面介绍两个比较特殊的案例:
循环依赖
这是在迁移 dash 时遇到了问题,第一次的配置:
(use-package dash
:vc (dash :url "https://github.com/magnars/dash.el.git"
:rev "2.19.1")
:defer t)
是最基本的用法,但是由于 dash 这个仓库内还有个 dash-functional.el
文件,里面的依赖有 dash,
并且 use-package 会先去加载 functional 这个文件,因此就出现了死循环!
通过阅读 package-vc.el 代码,找到了一个解法:
(use-package dash
:vc (dash :url "https://github.com/magnars/dash.el.git"
:ignored-files "dash-functional.el"
:rev "2.19.1")
:defer t)
利用 ignored-files
来过滤掉不需要的文件,这样就万事大吉了!
安装前执行脚本
有些包在安装时,需要执行些脚本,比如用了动态模块的就需要先编译好依赖,这时可以用:
:make
指定一个 Make 的 target,或:shell-command
指定 shell 命令
由于执行脚本会比较危险,因此 Emacs 提供了 package-vc-allow-build-commands
这个变量来控制是否运行脚本,默认是关闭的,可以配置成一个列表,表示运行执行脚本的包,下面是安装我之前写的 omg 时的用法:
(setq package-vc-allow-build-commands '(omg))
(use-package omg
:vc (omg :url "https://github.com/jiacai2050/oh-my-github"
:rev "v1.1.0"
:make "emacs-dyn"
:lisp-dir "emacs")
:config
(omg-setup))
收听方式
反馈
- 对节目有想法或发现内容错误?欢迎来信交流️