I restart my emacs a lot. All I want to do is create a function that kills the current emacs, only to spawn a new one in it's stead. Ideally, this would also work in a TTY.

  • 8
    Out of curiosity, why do you kill and immediately restart so often? – Dan Dec 16 '14 at 12:32
  • 1
    I very actively develop my .emacs.d, which means I restart emacs to remove whatever garbage I've blasted into my environment. There are a few other use-cases where I do this, but that's the biggest. – PythonNut Dec 16 '14 at 16:47
  • 1
    @PythonNut, I think you need to reframe your question a bit. Can you tell bash to restart after terminating? Or vi? Or any other process, as a rule? No, because that is outside of their scope of concerns, and is properly handled externally. In any case, what you really want is a way to reinitialize emacs, by clearing out its VM and re-running your init code (without killing its process). That would be useful and proper to emacs. I don't know if it exists, though :) – harpo Dec 16 '14 at 17:59
  • 4
    @harpo yes, I can get bash to restart with exec bash. I have no idea about vim. – PythonNut Dec 16 '14 at 21:56
  • 11
    FWIW, I'm more inclined to start a new instance of Emacs to test config changes, rather then exiting and restarting. Why? Because if my code has an error then Emacs might not be able to load my config when I restart it, and at that point I can't actually get a running instance with my normal settings, so I have to use a less-familiar editing environment to fix the bug. It won't happen often, but it's annoying when it does. I can run emacs -q and fix the problem of course, but I prefer to keep a 'good' instance running at all times when hacking on my configuration, just to be safe. – phils Jan 8 '15 at 4:34
up vote 21 down vote accepted

Note: I have wrapped the following in a package restart-emacs available here.


Here is an alternate way to achieve what you want using pure elisp (not really since you rely on a shell). The trick is to spawn off another emacs process just before current emacs is killed.

(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)))

The code to start a GUI version of emacs is straightforward. The code to start emacs in a terminal is a bit tricky. It uses the fact that you can pass a string to suspend-emacs which would be passed as terminal input to the parent process (the shell). From the documentation

(suspend-emacs &optional STUFFSTRING)

Stop Emacs and return to superior process. You can resume later. If `cannot-suspend' is non-nil, or if the system doesn't support job control, run a subshell instead.

If optional arg STUFFSTRING is non-nil, its characters are stuffed to be read as terminal input by Emacs's parent, after suspension.

So we basically suspend emacs just before it is killed tell the parent shell to resume currently suspended emacs (which is going to exit soon) and then launch another emacs process. Note that this does not work on platforms on which terminal emacs can/does not actually suspend but starts a subshell, for example on windows.

  • This does not work for me: when I run sh -c "emacs &" from the shell it stops with "emacs: standard input is not a tty" . (When I do M-x restart-emacs I don't even see that error message, Emacs just terminates.) – Constantine Dec 16 '14 at 18:01
  • Works for me under X. Won't work in a terminal because it redirects stdin and stdout to /dev/null; passing the parent tty to the subprocess is probably doable but trickier. – Beni Cherniavsky-Paskin Dec 16 '14 at 20:50
  • This works perfectly, and it actually scares me a bit. Why on earth is Emacs allowed to pass commands to its containing shell? – Radon Rosborough Dec 13 '16 at 19:28

As far as I know you cannot tell Emacs to re-start after terminating, but you can set the exit code so that the process that started Emacs in the first place can detect that you want to re-start.

For example, this shell script re-starts Emacs if it exited with the code 123.

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

Next, we define kill-emacs-and-restart that makes Emacs terminate with the exit code equal to the magic number recognized by the script:

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

Now if you run Emacs via this script you can re-start by M-x kill-emacs-and-restart (or bind it to a key sequence).

  • Nice way of skirting around the problem! I'll accept this if you can tell me why you cannot tell Emacs to re-start after terminating. Is this a technical limitation? – PythonNut Dec 16 '14 at 16:48
  • 3
    @PythonNut: As far as I know the only way to re-start a process is by using one of the functions from the exec... family (on POSIX systems, anyway). Emacs Lisp process control functions don't expose such low-level calls. I'm not an expert, though, so hopefully somebody more knowledgeable will chime in. – Constantine Dec 16 '14 at 18:11

Blatantly stolen from https://unix.stackexchange.com/questions/114238/is-it-possibe-to-change-parent-shells-working-directory-programmatically

Assuming I've got the syntax right for embedding " in a string, this should do it.

(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\")'"))
  • 9
    Please don't. This bypasses all of Emacs' internal cleanup and discards all current state (e.g. modified buffers) without confirmation. – lunaryorn Jan 8 '15 at 7:57
  • lunaryorn's warning is correct. – Joshua Jan 8 '15 at 16:11

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.