49

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.

6
  • 8
    Out of curiosity, why do you kill and immediately restart so often?
    – Dan
    Dec 16, 2014 at 12:32
  • 2
    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, 2014 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, 2014 at 17:59
  • 4
    @harpo yes, I can get bash to restart with exec bash. I have no idea about vim.
    – PythonNut
    Dec 16, 2014 at 21:56
  • 12
    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, 2015 at 4:34

4 Answers 4

31

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.

6
  • 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.) Dec 16, 2014 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. Dec 16, 2014 at 20:50
  • 2
    This works perfectly, and it actually scares me a bit. Why on earth is Emacs allowed to pass commands to its containing shell? Dec 13, 2016 at 19:28
  • which keybinding do you use for that ?
    – slk500
    Sep 30, 2019 at 10:51
  • I am getting Symbol’s function definition is void: \, error
    – alper
    Jun 8, 2020 at 21:57
32

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

2
  • 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, 2014 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. Dec 16, 2014 at 18:11
2

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

Update: As of emacs version 29.1 emacs now has the restart-emacs command built in.

** New command 'restart-emacs'.
This is like 'save-buffers-kill-emacs', but instead of just killing the current Emacs process at the end, it starts a new Emacs process (using the same command line arguments as the running Emacs process). 'kill-emacs' and 'save-buffers-kill-emacs' have also gained new optional arguments to restart instead of just killing the current process.

From the release notes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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