Emacs Server 启动方式探讨
tags: emacsclient
文章目录
在 Unix-like 的操作系统中,可以通过设置 EDITOR
环境变量来配置命令行工具(比如 git commit)默认的文本编辑器,比如:
export EDITOR=vim
# or
export EDITOR=emacs
通过这种方式,每一次都会新创建一个编辑器实例,对于 Vim 这种轻量级的编辑器还好,但对于 Emacs 这种十八般武艺样样精通的瑞士军刀来说就有些重了,理想状态是把 Emacs 作为一个类似浏览器的常驻进程,需要的时候 new 一个 frame/window 就好了,这时就用到了 Emacs Server 模式。
顾名思义,Server 模式只需要启动一次,后续使用时通过 emacsclient 进行连接即可。一般来说,在配置文件中添加如下命令即可:
(unless (server-running-p)
(server-start))
或者可以通过在命令行执行 emacs --daemon
,它会在加载完用户配置后,自动调用 server-start
,区别于前者,这种方式重复调用时会报错:
Starting Emacs daemon.
Unable to start the daemon.
Another instance of Emacs is running the server, either as daemon or interactively.
You can use emacsclient to connect to that Emacs process.
Error: server did not start correctly
笔者经过一番探索,发现其实可以直接通过 emacsclient 来直接启动 server 模式,命令如下:
emacsclient -a "" -c -n "$@"
-a
是 alternate-editor 的简写,意思是在连接 server 失败时的替代编辑器,当为空值时,会自动执行emacs --daemon
,然后再去连接。这样就解决了完美解决了重复调用 daemon 时的错误,而且也能在第一次调用时启动 server 模式-c
表示新创建一个 frame,而不是复用已有的-n
表示执行完该命令后,立刻退出,不用等待 server 返回。这也非常重要,否则终端就不会立刻返回了。
通过把上面的命令封装成 shell 脚本或做成 alias(比如 e
),可以很方便的在命令行调用,比如 e ~/.bashrc
,比 vim 还方便。
stdin
在 Vim 中可以用 vim -
读取标准输入的内容,比如
echo 123 | vim -
很遗憾,默认 emacs/emacsclient 命令是不支持这种方式的,但可以通过间接的方式实现:
# cat ~/bin/e
function _emacsclient
{
emacsclient -a "" -c -n "$@"
}
function main
{
# If the argument is - then write stdin to a tempfile and open the
# tempfile.
if [[ $# -ge 1 ]] && [[ "$1" == - ]]; then
tempfile="$(mktemp -t emacs-stdin-$USER.XXXXXXX)"
cat - > "$tempfile"
_emacsclient --eval "(find-file \"$tempfile\")" \
--eval '(set-visited-file-name nil)' \
--eval '(rename-buffer "*stdin*" t))'
else
_emacsclient "$@"
fi
}
main "$@"
上述脚本通过重定向到一个临时文件的方式来解决,这样 emacsclient 就能够像 Vim 一样读取 stdin 了。
环境变量
通过在命令行启动 Emacs 还有一个额外的好处是:自动继承当前 Shell 中的所有环境变量,这样就不需要 exec-path-from-shell 这类插件了。
收听方式
反馈
- 对节目有想法或发现内容错误?欢迎来信交流️