先前手机打字不便,来电脑上做些补充。
用 Elisp 写命令行工具其实有不少相当完备的例子和辅助工具:
-
Cask: Elisp 项目管理工具,package 开发必备。
- ert-runner: Opinionated Ert testing workflow (Cask 插件)。
- github-elpa: Build and Publish Your Own ELPA Repositories with GitHub Pages (Cask 插件)。
-
Eldev: 另一款不错的 Elisp 项目管理工具。
-
ecuckes: 集成测试工具 Cucumber 的 Elisp 移植。
-
epm: 论坛大佬 xuchunyang 写的包管理工具。
-
bin/doom DoomEmacs 的命令行工具。
-
commander: 命令行参数解析库:
(commander (name "my-awesome-program") (option "--help" "Show usage information" commander-print-usage))
前面提到的文章《emacs-script中的那些坑》总结得并不全面,综合《想到一种启动 Emacs Script 的方法》可知:
-
--script并未禁止所有的初始化动作,还得加-Q/--quick参数 -
但
#!/usr/bin/env emacs -Q --script无法在 Linux 下使用,因为 Linux 下 shebang 不会拆分[1](Mac 下没问题)(
据 #15 说加 -S参数可解)。 29 的 -x 就是为了解决这个问题[2],并未增加什么实际的功能:$ emacs --help | rg '^-x' -A2 -x to be used in #!/usr/bin/emacs -x and has approximately the same meaning as -Q --script ^^^^^^^^^^^^^^ -
#!/usr/bin/env emacs --script还有个问题,就是参数会被 Emacs 先拦截掉,例如:$ cat ./bin/hello.el #!/usr/bin/env emacs --script (message "Hello World!") $ ./bin/hello.el --version GNU Emacs 29.0.50 ⎫ Copyright (C) 2022 Free Software Foundation, Inc. | GNU Emacs comes with ABSOLUTELY NO WARRANTY. ⎬ !!! You may redistribute copies of GNU Emacs | under the terms of the GNU General Public License. | For more information about these matters, see the file ... ⎭ -
":"; exec emacs --quick --script "$0" -- "$@" # -*- mode: emacs-lisp; lexical-binding: t; -*-可以解决参数问题,但它里边的lexical-binding: t不起作用:$ cat ./bin/hello.el #!/bin/sh ":"; exec emacs --quick --script "$0" -- "$@" # -*- mode: emacs-lisp; lexical-binding: t; -*- (message "Hello World!") (message "arguments: %S" command-line-args-left) (message "lexical-binding: %s" lexical-binding) $ ./bin/hello.el --help Hello World! arguments: ("--" "--help") lexical-binding: nil ^^^
如果不是非得用单个文件实现,可以不必拘泥于 shebang 魔法或是等 29 的 -x。用 shell script + elisp 也能很好的实现(例如上面提到的 Cask/Eldev/ecuckes/epm),还能避开上述一些问题,我的一款即将完工的命令行工具也是采用这种模式。