如何确定某个函数是哪一版本的Emacs引入的?


#1

如题所示,或者说,如何确定自己写的el文件可以适用的最低版本的Emacs?


#2

Changelog


#3

有几种思路配合起来:

  1. 根据经验;
  2. M-x package-lint-current-buffer
  3. 用各种版本的 Emacs 进行 Byte Compile,检查 Warnings(一般在 CI 做这样的测试)
  4. C-u C-h n

#4

我的 elisp-demos.el 也试图提供这样的信息:

* assoc-delete-all
:PROPERTIES:
:added:    26.2
:changes:  27.1 The TEST argument is added.
:END:

但是目前仅仅提供了几个。


#5

package-lint-current-buffer 或其它文档提供的信息都有限。

最靠谱就是本地准备好各种版本的 Emacs,把 byte-compile 和测试用例先跑一遍,然后再推送到 github。

问题其实不止函数在哪个版本引入,还包括参数变更等等各种情况。例如 assoc 函数,最开始是这样的:(assoc KEY LIST),后来又增加了一个参数,变成了:(assoc KEY LIST &optional TESTFN)

⋊> /Applications/Emacs-25.3.1.app/Contents/MacOS/Emacs --batch --eval "(princ (assoc 'foo (list (cons 'foo 1)) 'eq))"
Wrong number of arguments: assoc, 3

⋊> /Applications/Emacs-26.1.app/Contents/MacOS/Emacs --batch --eval "(princ (assoc 'foo (list (cons 'foo 1)) 'eq))"
(foo . 1)

#6

还有些函数本身也会有变化,比如下面这个表达式,Emacs 25 正常执行,而 Emacs 24.5 会报错

(pcase nil
  ('nil t))

Emacs 24 只能用:

(pcase nil
  (`nil t))

因为 pcase 从 Emacs 25 才开始支持 QUOTE Pattern。

不像上面提到的函数没定义或者参数数目多余,这样的问题 byte compiler 无法检查出来。


#7

所以还是要写测试,测试覆盖到了,才有底气说没问题。

写代码的时侯,可能会记得某些个比较亮眼的特性/函数是从哪个版本开始引入的, 而实际上每个 Emacs 版本都可能会引入新的函数、增强/扩展/删除旧的函数,那些不太引人注意的函数也可能存在兼容性问题。

我一般会在本地用各个版本的 Emacs 把测试跑一遍,兼容性问题在这一步基本都能发现。

然后推到 githu 让 Travis 再验证一遍,这时如果还有问题,通常是因为环境差异,例如 travis 镜像默认没有安装一些必要资源。


#8

能写测试最好了,尽管依旧可能会存在测试没覆盖到的情况。不过,大部分包连检查 Byte Compiler 都做不到,更别提测试了,我觉得主要是因为:

  • CI 下安装各个版本的 Emacs 比较困难;
  • Emacs 的包管理器跟不上,没法可靠地、无需用户介入地处理依赖;
  • Emacs 是个用户程序,很难测试包含用户交互的代码;
  • 开发者不够重视。

#9

travis 可以啊,我看 Centaur Emacs 就这么搞的


#10

这就是我说的「比较困难」,对比:

language: python
python:
  - "2.6"
  - "2.7"
  - "3.3"
  - "3.4"
  - "3.5"

#11

EVM 提供的 Emacs 有个小问题是没有 libxml2 支持,所以没法测试 libxml-parse-html-region


#12

有必要那么多么?我觉得大版本和master branch分别跑一次就可以了


#13

指 Python 的版本么?(我只是举个例子来说明安装不同版本的 Python 比较容易)


#14

官方支持的肯定不能比啦