[已解决]在 emacs 批处理中涉及第三方插件时,require 的正确方式是什么?

用 Emacs 直接打开一个 Org 文件,M-: 执行 (org-hugo-export-wim-to-md :all-subtrees) 。 它调用 ox-hugo 这个第三方插件(第三方包)来完成导出工作,一切正常。

现在我想把它写成一个脚本(两个 EOF 之间的行就是 elisp 脚本,只不过 $1 会被 bash 先展开,并且前面已经有 emacs 了所以不需要再加 shebang):

#!/bin/bash
emacs --script <(cat<<EOF
(require 'ox-hugo)
(find-file "$1")
(org-hugo-export-wim-to-md :all-subtrees)
EOF)

运行,报错:Error: file-missing ("Cannot open load file" "没有那个文件或目录" "ox-hugo")

我感到有些疑惑的是,ox-hugo 是已经从 melpa 用 usepackage 安装了的,配置如下:

(use-package ox-hugo
  :ensure t
  :pin melpa
  :after ox)

但不管怎么说,那就手动 load 一下吧。在 elisp 部分加入这句:

(load "~/.emacs.d/elpa/ox-hugo-20240305.1923/ox-hugo.el")

这次报错变成了 Error: file-missing ("Cannot open load file" "没有那个文件或目录" "tomelr") 。 显然,这是 ox-hugo.el 中的 require 语句造成的报错:

(require 'tomelr)                       ;For `tomelr-encode'

(require 'ox-blackfriday)

(require 'ffap)                         ;For `ffap-url-regexp'
(require 'ob-core)                      ;For `org-babel-parse-header-arguments'
;; `org-refile.el' is new in Org 9.4
;; https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=f636cf91b6cbe322eca56e23283f4614548c9d65
(require 'org-refile nil :noerror)      ;For `org-get-outline-path'

(require 'org)
(require 'org-id)                       ;For `org-id-find'

也就是说它 require 了一堆别的。为了解决这个问题,按照我目前的思路,还要继续在 ~/.emacs.d/elpa/ 下面找到对应的插件来 load,它们继而又依赖更多的插件——显然这个思路是不太对的。

为了能正常 require,正确的方式是什么呢?

你可能需要 (package-initialize)

1 个赞

这并不是这些包之间的 require 关系有问题,你使用了 batch 方式启动 Emacs 进程,这种情况下,它不会加载用户配置,也不会进行 package.el 相关的初始化。

如果你需要 package.el 安装的一些包,可以试着在代码中加入 (package-activate-all) package-initialize

1 个赞

实测两种方法都可行,谢谢两位。

之前做过一张图,顺便贴一下,是 Emacs 28 的,不过 29 应该也没太大变化。

9 个赞