如何设置 emacsclient 的退出状态

如何设置 emacsclient 的退出状态

我发现自己使用主 Emacs 会话(OSX 中的 CocoaEmacs)来编辑 bash 命令行。为此,我将 EDITOR 设置为emacsclient。然后我在 Emacs 中编辑该行并保存并退出该缓冲区——通常使用"C-x #"which 执行(server-edit)

问题是有时我正在编辑一行,然后意识到我不想真正执行该行(后悔了)。问题是 bash 根据返回状态确定是否执行该行。

我希望有两个选择。

  1. 如果我点击"C-x #"保存缓冲区并返回退出代码0(即,我已经完成编辑并且准备让 bash 处理它)。

  2. 如果我关闭缓冲区,则不保存缓冲区,关闭它并返回非零退出代码。即使我必须使用替代绑定,我也不会介意。

部分的解决方案就是注释该行。我不认为这是一个选项,因为我在 Emacs 中编辑命令行的正常原因是我正在处理多行内容。

答案1

在相对较新的 Emacs 版本中(例如,在我的 Emacs 24.2 副本中,但不是 OS X 的 emacs 22.1 发行版中),您可以编写 Elisp 代码,将命令发送到 emacsclient,告诉它以错误退出状态退出。

这比听起来容易。

有一个缓冲区局部变量,server-buffer-clients,其中包含连接到缓冲区的客户端。并且该函数server-send-string可用于按照server-process-filter协议传达命令。

例如:

(server-send-string (car server-buffer-clients) "-error die")

导致与缓冲区关联的 emacsclient(之一)立即发出文本

*ERROR*: die

然后以退出代码 1 退出。


因此,定义一个可以从 emacs 本身调用的交互式函数来终止 emacsclients 是相当容易的:

(defun tell-emacsclients-for-buffer-to-die ()
  "Sends error exit command to every client for the current buffer."
  (interactive)
  (dolist (proc server-buffer-clients)
    (server-send-string proc "-error die")))

在您的文件中包含上述内容.emacs(以及足够新的 Emacs 版本)后,您可以调用M-x tell-emacsclients-for-buffer-to-die以使 emacsclients 以错误状态退出。(当然,您可以将此功能绑定到适当的备用键序列。)


脚注

理想情况下,可以将上述函数与函数上的钩子结合起来,server-kill-buffer以实现原始问题中的目标编号 (2.)。(也就是说,在没有通过的情况下终止缓冲区C-x #应该会触发 emacsclient 的相同错误退出。)

但是,我尝试将其添加到kill-buffer-hook失败了,因为在运行钩子之后,该server-kill-buffer函数被放在列表的最前面,因此默认函数将首先运行。(可以修复后续问题,但我还不确定在 Elisp 控制流中将代码放在哪里才能做到这一点。)kill-buffer-hookserver-visit-hookserver-kill-bufferkill-buffer-hook

更新:好的,这里有一个真正黑客的方法来实现上述目标:

(defun kill-buffer-with-special-emacsclient-handling ()
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

(global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling)

更新 2:稍微更强大的变体:

(defun kill-buffer-with-special-emacsclient-handling ()
  "Wrapper around kill-buffer that ensures tell-emacsclients-for-buffer-to-die is on the hooks"
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

;; (global-set-key (kbd "C-x k") 'kill-buffer)

(defun install-emacsclient-wrapped-kill-buffer ()
  "Installs wrapped kill-buffer with special emacsclient handling.
Best not to install it unconditionally because the server is not
necessarily running."
  (interactive)
  (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling))

(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer)

答案2

只需在运行 bash 的终端中按下即可Ctrl+C。这将取消编辑,并将原始行推送到历史记录中。如果由于 Emacs 正在同一终端中运行而无法直接执行此操作,请emacsclient通过您选择的方式终止该进程。

相关内容