我发现自己使用主 Emacs 会话(OSX 中的 CocoaEmacs)来编辑 bash 命令行。为此,我将 EDITOR 设置为emacsclient
。然后我在 Emacs 中编辑该行并保存并退出该缓冲区——通常使用"C-x #"
which 执行(server-edit)
。
问题是有时我正在编辑一行,然后意识到我不想真正执行该行(后悔了)。问题是 bash 根据返回状态确定是否执行该行。
我希望有两个选择。
如果我点击
"C-x #"
保存缓冲区并返回退出代码0
(即,我已经完成编辑并且准备让 bash 处理它)。如果我关闭缓冲区,则不保存缓冲区,关闭它并返回非零退出代码。即使我必须使用替代绑定,我也不会介意。
一部分的解决方案就是注释该行。我不认为这是一个选项,因为我在 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-hook
server-visit-hook
server-kill-buffer
kill-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
通过您选择的方式终止该进程。