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.
4 Answers
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 doM-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
-
2This 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
-
-
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? 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
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\")'"))
-
13Please don't. This bypasses all of Emacs' internal cleanup and discards all current state (e.g. modified buffers) without confirmation.– user227Jan 8, 2015 at 7:57
-
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
.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.bash
to restart after terminating? Orvi
? 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 :)bash
to restart withexec bash
. I have no idea about vim.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.