突发奇想:emacs能否像python解释器一样地使用呢?这就让emacs在实际工作中有大量用武之地了!这个有可能吗?

先前手机打字不便,来电脑上做些补充。

用 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 的方法》可知:

  1. --script 并未禁止所有的初始化动作,还得加 -Q/--quick 参数

  2. #!/usr/bin/env emacs -Q --script 无法在 Linux 下使用,因为 Linux 下 shebang 不会拆分[1](Mac 下没问题)(:warning:#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
                                  ^^^^^^^^^^^^^^
    
  3. #!/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 ... ⎭
    
  4. ":"; 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),还能避开上述一些问题,我的一款即将完工的命令行工具也是采用这种模式。


6 个赞