从emacs中重新启动emacs


44

我经常重启我的emacs。我要做的就是创建一个杀死当前emacs的函数,而只是产生一个新的emacs。理想情况下,这也将在TTY中起作用。


8
出于好奇,为什么您如此频繁地杀死并立即重启?

2
我非常积极地开发自己的.emacs.d,这意味着我将重新启动emacs来清除我抛入环境中的所有垃圾。我还有其他一些用例,但这是最大的。
PythonNut 2014年

1
@PythonNut,我认为您需要重新构建问题。您可以告诉bash终止后重新启动吗?还是vi?还是其他任何程序?不可以,因为这超出了他们的关注范围,并且可以从外部进行适当处理。无论如何,您真正想要的是一种通过清除VM并重新运行您的初始化代码(而不终止其进程)来重新初始化 emacs 的方法。这对于emacs有用且适当。不过,我不知道它是否存在:)
harpo 2014年

4
@harpo是的,我可以bash使用重新启动exec bash。我对vim一无所知。
PythonNut 2014年

11
FWIW,我更倾向于启动一个的Emacs实例来测试配置更改,而不是退出并重新启动。为什么?因为如果我的代码有错误,那么Emacs在重新启动配置时可能无法加载我的配置,并且那时我实际上无法获得具有常规设置的正在运行的实例,因此我必须使用不太熟悉的编辑修复错误的环境。它不会经常发生,但是很烦。我emacs -q当然可以运行并解决该问题,但是为了安全起见,我更喜欢在入侵我的配置时始终保持“良好”实例运行。
phils 2015年

Answers:


25

注意:我将以下内容包装在此处restart-emacs提供的包中。


这是使用纯elisp达到您想要的目的的另一种方法(因为您依赖于shell,所以并非如此)。诀窍是在杀死当前emacs之前产生另一个emacs进程。

(defun launch-separate-emacs-in-terminal ()
  (suspend-emacs "fg ; emacs -nw"))

(defun launch-separate-emacs-under-x ()
  (call-process "sh" nil nil nil "-c" "emacs &"))

(defun restart-emacs ()
  (interactive)
  ;; We need the new emacs to be spawned after all kill-emacs-hooks
  ;; have been processed and there is nothing interesting left
  (let ((kill-emacs-hook (append kill-emacs-hook (list (if (display-graphic-p)
                                                           #'launch-separate-emacs-under-x
                                                         #'launch-separate-emacs-in-terminal)))))
    (save-buffers-kill-emacs)))

启动emacs的GUI版本的代码很简单。在终端中启动emacs的代码有些棘手。它使用以下事实:您可以传递一个字符串,suspend-emacs该字符串将作为终端输入传递给父进程(shell)。从文档

(暂停-emacs和可选的填充)

停止Emacs并返回上级流程。您可以稍后再继续。如果cannot-suspend不为nil,或者系统不支持作业控制,则运行subshel​​l。

如果可选的arg STUFFSTRING为非nil,则暂停后,其字符将被Emacs的父级填充为终端输入读取。

因此,我们基本上在将emacs杀死之前将其挂起,告诉父shell恢复当前已暂停的emacs(这将很快退出),然后启动另一个emacs进程。请注意,这在终端emacs可以/实际上不能挂起但启动子Shell的平台上不起作用,例如在Windows上。


这对我不起作用:当我sh -c "emacs &"从shell 运行时,它以“ emacs: standard input is not a tty” 停止。(当我什至M-x restart-emacs没有看到该错误消息时,Emacs就会终止。)
Constantine

在X下为我工作。在终端机上不起作用,因为它将stdin和stdout重定向到/ dev / null;将父tty传递给子流程可能是可行的,但比较棘手。
Beni Cherniavsky-Paskin 2014年

1
这很完美,实际上让我有些害怕。到底为什么允许Emacs将命令传递到其包含的shell?
Radon Rosborough,2013年

您为此使用哪种键绑定?
slk500

32

据我所知,您不能告诉Emacs在终止后重新启动,但是您可以设置退出代码,以便首先启动Emacs的进程可以检测到您要重新启动。

例如,如果此shell脚本以代码123退出,则会重新启动Emacs。

#!/bin/sh
while emacs -nw "$@"; [ $? = 123 ]; do :; done

接下来,我们定义kill-emacs-and-restart使Emacs终止的退出代码等于脚本识别的幻数:

(defun kill-emacs-and-restart ()
  (interactive)
  (kill-emacs 123))

现在,如果通过此脚本运行Emacs,则可以重新启动M-x kill-emacs-and-restart(或将其绑定到键序列)。


解决问题的好方法!如果您能告诉我原因,我将接受you cannot tell Emacs to re-start after terminating。这是技术限制吗?
PythonNut 2014年

3
@PythonNut:据我所知,重新启动进程的唯一方法是使用该exec...系列的功能之一(无论如何在POSIX系统上)。Emacs Lisp流程控制功能不会公开此类低级调用。我不是专家,不过,在这么希望别人更了解就会发出响声。
康斯坦丁

2

https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-以编程方式公然被盗

假设我在字符串中嵌入“”的语法正确,这应该可以做到。

(defun restart-emacs ()
  (call-process "sh" nil nil nil "-c" "gdb -p $(ps h -o ppid -p $$) -ex 'call execl(\"/bin/sh\", \"/bin/sh\", \"-c\", \"exec emacs\")'"))

11
请不要。这会绕过Emacs的所有内部清理,并丢弃所有当前状态(例如,修改后的缓冲区),而不进行确认
lunaryorn

lunaryorn的警告是正确的。
约书亚2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.