确定Emacs server是否启动, 或者说server-running-p的迷思
一个小问题:如何确定当前Emacs实例是否启动了服务器?
快速搜索一下,我们可以得到三种方法: server-mode=, =(daemonp)
和 (server-running-p)
.
这太多了,但是其中一个肯定是正确答案对吗? 然而, 并不是. 因为这个小问题的真正答案是:你无能为力。
- 且仅当服务器使用
server-mode
函数启动时server-mode
的值才为t=。但是我们还有其他方法可以启动服务器,比如 =M-x server-start
或emacs --daemon
。 - 且仅当Emacs在守护进程模式下启动时,
(daemonp)
才会返回t
.
那么 (server-run-p)
呢?它看起来可能很不错,但是也有坑.
它初看起来很不错:执行 M-x server-start
后, (server-running-p)
会返回 t
!
那么我们是不是就可以选它了呢? 还不行!
让我们启动一个新的Emacs实例,在不启动服务器的情况下执行 (server-run-p)
会发现依然返回 t
!
怎么回事?事实上 (server-running-p)
有点名不符实. 以下是其完整的源代码:
(defun server-running-p (&optional name) "Test whether server NAME is running. Return values: nil the server is definitely not running. t the server seems to be running. something else we cannot determine whether it's running without using commands which may have to wait for a long time." (unless name (setq name server-name)) (condition-case nil (if server-use-tcp (with-temp-buffer (insert-file-contents-literally (expand-file-name name server-auth-dir)) (or (and (looking-at "127\.0\.0\.1:[0-9]+ \([0-9]+\)") (assq 'comm (process-attributes (string-to-number (match-string 1)))) t) :other)) (delete-process (make-network-process :name "server-client-test" :family 'local :server nil :noquery t :service (expand-file-name name server-socket-dir))) t) (file-error nil)))
doc-string中描述了恐怖的细节。函数中的 -p
后缀说明这是一个谓词,即布尔函数。
但在 server-running-p
, 返回 非 nil
值并不一定就是响亮而明确的 “是!”, 它的意思其实是“嗯,也许吧,谁知道呢?”
这是第三种可能,因为Emacs并不是黑白分明的。
但是这个函数做什么呢?它试图确定一个名叫 NAME
的服务器是否正在运行,方法是假设该服务器的配置与正在运行的实例完全一致。
它可能最终会查看当前服务器的套接字文件,或者尝试启动一个TCP连接(这个开销非常昂贵)。
你可能会在构建mode line时调用 server-running-p
函数: 但是它会让你立刻冻结Emacs运行而且还无法恢复.
它的使用场景目前还不太清楚. 它无法确定正在运行的实例是否启用了服务器 --- 但是它会使用该服务器的配置去搜索潜在的完全不同的其他服务器.