《elisp 每日一练》——通过GitHub仓库安装package

《elisp 每日一练》——通过GitHub仓库安装package

Masimaro
2026-11-14 / 0 评论 / 1 阅读 / 正在检测是否收录...

各位读者,周末愉快。本次接着来更新有关elisp 的相关内容。我有好多天没有更新了,读者对前面的内容不知道还记得多少呢。在前面我们学会了从melpa 和 elpa 中下载、安装、更新package,并且在了解原理之后搭建自己的备份。今天我们来讨论另一种类型的package 管理

背景知识

melpa和 elpa 可以说是Emacs官方和社区的包管理仓库,通过 archive-contents 记录包的信息。但是有时候我们需要的package 可能没有发布在 melpa 和 elpa 中,仅仅发布在GitHub或者gitlab这种代码仓库中。这种包仅仅通过 package-install 是不够的。

从Emacs 29 开始,Emacs新增了 package-vc 模块专门来处理这种类型的包。它的基本原理是通过 git 命令将远程的仓库克隆到本地然后执行字节编译,并集成到包管理系统中。从前面我们介绍过的包管理的机制,它只负责从下载到字节编译的过程,而后这个包仍然由包管理系统接管。也就是说后面我们通过前面介绍的手段进行包的删除、或者自动删除操作。第一次安装以后,启动Emacs也是由Emacs的包管理进行加载。

默认我们可以使用 package-vc-install 安装。它是交互式命令,也可以在代码中调用。它的签名如下:

(package-vc-install PACKAGE &optional REV BACKEND NAME)
  • PACKAGE 是我们指定的包,它有三种形式:
  • 符号:这种情况,它会从melpa 或者elpa,或者另外的提供的包仓库中查找包信息,并通过信息里面记录的包的地址进行下载
  • 字符串:通过字符串的形式直接给出包的下载地址, 此时Emacs会根据url地址来决定包名
  • cons cell: 使用 (NAME . SPEC) 手动指定包名和详细的规格说明, NAME 是包的名称,SPEC 为plist 结构,用于指定特殊配置
  • REV 表示需要下载的版本。我们可以填 commit id、分支名或标签名
  • BACKEND 表示当前采用的版本管理系统,默认不填,Emacs会根据url地址来判断
  • NAME 包名称,一般不填,由Emacs自行根据url决定

例如我们以在之前配置Emacs时用到的 awesome-tab 为例,可以通过如下方式安装

(package-vc-install "https://github.com/manateelazycat/awesome-tab")

也可以安装指定分支或者指定tag 指定 commit id 的版本:

(package-vc-install "https://github.com/manateelazycat/awesome-tab" "1dc9094")

如果我们未指定版本或者分支,那么以后只要公共仓库主版本更新了,我们可以通过 package-upgrade 或者 package-upgrade-all 来更新它。

因为GitHub之类的仓库管理权主要在作者,因此稳定性无法得到保证,有时候我们发现最新版引入一些bug导致我们的工作流无法正常工作。因此我们可能需要进行版本回退。一般的方法是,通过 package-vc-install 加上对应的commit id 固定版本,然后执行一遍,Emacs会根据你的要求自动切换到指定的commit id

练习

本次的练习我们在之前的 my-require 之上加上:vc 参数,它里面可以通过 (:url "" :rev "" :name 'my-pack) 之类的配置支持从github等代码仓库中下载更新第三方包:

(defun my-require(package &optional filename noerror vc)
  "自动安装或者更新所依赖的包"
  (if vc
      (let ((url (plist-get vc :url))
            (rev (plist-get vc :rev)))
        (when url
          (package-vc-install url rev nil package)))
    (unless (package-installed-p package)
    (package-refresh-contents t)
    (package-install package))
  (when (package-installed-p package)
        (package-refresh-contents t)
        (ignore-errors (package-upgrade package))))
  (require package filename noerror))

调用时我们可以这样使用

(my-require 'magit)
(my-require 'awesome-tab nil nil '(:url "https://github.com/manateelazycat/awesome-tab"))

总结

本篇我们主要介绍了下载安装GitHub、gitlab 等代码库中的package。我们利用emacs 29 版本的 package-vc 模块。主要使用 package-vc-install 安装指定版本的代码,接着后面的管理仍然交给原生的 package 模块

0

评论 (0)

取消