summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Ingebrigtsen <larsi@gnus.org>2022-04-17 13:37:51 +0200
committerLars Ingebrigtsen <larsi@gnus.org>2022-04-17 13:37:51 +0200
commit5be9a9cacfaae1959c4b95c45c146044a181ad20 (patch)
tree23e138d4719a46cf36538c89ca7cc694a387bc6a
parent0829c6836eff14dda0cf8b3047376967f7b000f4 (diff)
downloademacs-5be9a9cacfaae1959c4b95c45c146044a181ad20.tar.gz
Add a new command `restart-emacs'
* doc/lispref/os.texi (Killing Emacs): Document it. * lisp/files.el (save-buffers-kill-emacs): Add new RESTART parameter. (restart-emacs): New function. * src/emacs.c (terminate_due_to_signal, Fkill_emacs): Take an optional RESTART parameter. * test/lisp/files-tests.el (files-tests-save-buffers-kill-emacs--confirm-kill-processes): * src/xterm.c (x_connection_closed): * src/xsmfns.c (Fhandle_save_session): * src/keyboard.c (Fcommand_error_default_function, command_loop) (command_loop_1, read_menu_command, read_event_from_main_queue) (read_key_sequence, quit_throw_to_read_char): * src/eval.c (process_quit_flag): Adjust Fkill_emacs callers.
-rw-r--r--doc/lispref/os.texi13
-rw-r--r--etc/NEWS12
-rw-r--r--lisp/files.el19
-rw-r--r--src/emacs.c21
-rw-r--r--src/eval.c2
-rw-r--r--src/keyboard.c18
-rw-r--r--src/xdisp.c2
-rw-r--r--src/xsmfns.c2
-rw-r--r--src/xterm.c2
-rw-r--r--test/lisp/files-tests.el2
10 files changed, 68 insertions, 25 deletions
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 8366689640f..eea0ab8f6bc 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -699,7 +699,7 @@ If you started Emacs from a terminal, the parent process normally
resumes control. The low-level primitive for killing Emacs is
@code{kill-emacs}.
-@deffn Command kill-emacs &optional exit-data
+@deffn Command kill-emacs &optional exit-data restart
This command calls the hook @code{kill-emacs-hook}, then exits the
Emacs process and kills it.
@@ -714,6 +714,10 @@ input) can read them.
If @var{exit-data} is neither an integer nor a string, or is omitted,
that means to use the (system-specific) exit status which indicates
successful program termination.
+
+If @var{restart} is non-@code{nil}, instead of just exiting at the
+end, start a new Emacs process, using the same command line arguments
+as the currently running Emacs process.
@end deffn
@cindex SIGTERM
@@ -756,6 +760,13 @@ the remaining functions in this hook. Calling @code{kill-emacs}
directly does not run this hook.
@end defopt
+@deffn Command restart-emacs
+This command does the same as @code{save-buffers-kill-emacs}, but
+instead of just killing the current Emacs process at the end, it'll
+restart a new Emacs process, using the same command line arguments as
+the currently running Emacs process.
+@end deffn
+
@node Suspending Emacs
@subsection Suspending Emacs
@cindex suspending Emacs
diff --git a/etc/NEWS b/etc/NEWS
index 71d1e90d833..0245ec8c689 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -195,6 +195,15 @@ methods instead.
* Changes in Emacs 29.1
+++
+** 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 parameters to restart instead of just killing the current
+process.
+
++++
** New user option 'mouse-drag-and-drop-region-cross-program'.
If non-nil, this option allows dragging text in the region from Emacs
to another program.
@@ -1451,7 +1460,8 @@ compliant.
+++
** New macro 'setopt'.
This is like 'setq', but is meant to be used for user options instead
-of plain variables, and uses 'custom-set'/'set-default' to set them.
+of plain variables, and
+uses 'custom-set'/'set-default' to set them.
+++
** New utility predicate 'mode-line-window-selected-p'.
diff --git a/lisp/files.el b/lisp/files.el
index b5ec7d45005..80180276a99 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7762,14 +7762,17 @@ prompt the user before killing them."
:group 'convenience
:version "26.1")
-(defun save-buffers-kill-emacs (&optional arg)
+(defun save-buffers-kill-emacs (&optional arg restart)
"Offer to save each buffer, then kill this Emacs process.
With prefix ARG, silently save all file-visiting buffers without asking.
If there are active processes where `process-query-on-exit-flag'
returns non-nil and `confirm-kill-processes' is non-nil,
asks whether processes should be killed.
+
Runs the members of `kill-emacs-query-functions' in turn and stops
-if any returns nil. If `confirm-kill-emacs' is non-nil, calls it."
+if any returns nil. If `confirm-kill-emacs' is non-nil, calls it.
+
+If RESTART, restart Emacs after killing the current Emacs process."
(interactive "P")
;; Don't use save-some-buffers-default-predicate, because we want
;; to ask about all the buffers before killing Emacs.
@@ -7823,7 +7826,7 @@ if any returns nil. If `confirm-kill-emacs' is non-nil, calls it."
(run-hook-with-args-until-failure 'kill-emacs-query-functions)
(or (null confirm)
(funcall confirm "Really exit Emacs? "))
- (kill-emacs))))
+ (kill-emacs nil restart))))
(defun save-buffers-kill-terminal (&optional arg)
"Offer to save each buffer, then kill the current connection.
@@ -7838,6 +7841,16 @@ only these files will be asked to be saved."
(if (frame-parameter nil 'client)
(server-save-buffers-kill-terminal arg)
(save-buffers-kill-emacs arg)))
+
+(defun restart-emacs ()
+ "Kill the current Emacs process and start a new one.
+This goes through the same shutdown procedure as
+`save-buffers-kill-emacs', but instead of killing Emacs and
+exiting, it re-executes Emacs (using the same command line
+arguments as the running Emacs)."
+ (interactive)
+ (save-buffers-kill-emacs nil t))
+
;; We use /: as a prefix to "quote" a file name
;; so that magic file name handlers will not apply to it.
diff --git a/src/emacs.c b/src/emacs.c
index a35996c07aa..50b1628d207 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -427,7 +427,7 @@ terminate_due_to_signal (int sig, int backtrace_limit)
don't care about the message stack. */
if (sig == SIGINT && noninteractive)
clear_message_stack ();
- Fkill_emacs (make_fixnum (sig));
+ Fkill_emacs (make_fixnum (sig), Qnil);
}
shut_down_emacs (sig, Qnil);
@@ -2740,21 +2740,25 @@ sort_args (int argc, char **argv)
xfree (priority);
}
-DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 1, "P",
+DEFUN ("kill-emacs", Fkill_emacs, Skill_emacs, 0, 2, "P",
doc: /* Exit the Emacs job and kill it.
If ARG is an integer, return ARG as the exit program code.
If ARG is a string, stuff it as keyboard input.
Any other value of ARG, or ARG omitted, means return an
exit code that indicates successful program termination.
+If RESTART is non-nil, instead of just exiting at the end, start a new
+Emacs process, using the same command line arguments as the currently
+running Emacs process.
+
This function is called upon receipt of the signals SIGTERM
or SIGHUP, and upon SIGINT in batch mode.
-The value of `kill-emacs-hook', if not void,
-is a list of functions (of no args),
-all of which are called before Emacs is actually killed. */
+The value of `kill-emacs-hook', if not void, is a list of functions
+(of no args), all of which are called before Emacs is actually
+killed. */
attributes: noreturn)
- (Lisp_Object arg)
+ (Lisp_Object arg, Lisp_Object restart)
{
int exit_code;
@@ -2801,6 +2805,11 @@ all of which are called before Emacs is actually killed. */
eln_load_path_final_clean_up ();
#endif
+ if (!NILP (restart))
+ {
+ execvp (*initial_argv, initial_argv);
+ }
+
if (FIXNUMP (arg))
exit_code = (XFIXNUM (arg) < 0
? XFIXNUM (arg) | INT_MIN
diff --git a/src/eval.c b/src/eval.c
index a1cebcd0257..6b1e12b8232 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1613,7 +1613,7 @@ process_quit_flag (void)
Lisp_Object flag = Vquit_flag;
Vquit_flag = Qnil;
if (EQ (flag, Qkill_emacs))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (EQ (Vthrow_on_input, flag))
Fthrow (Vthrow_on_input, Qt);
quit ();
diff --git a/src/keyboard.c b/src/keyboard.c
index e569f8f34c9..19c8fdf1dc0 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1059,7 +1059,7 @@ Default value of `command-error-function'. */)
print_error_message (data, Qexternal_debugging_output,
SSDATA (context), signal);
Fterpri (Qexternal_debugging_output, Qnil);
- Fkill_emacs (make_fixnum (-1));
+ Fkill_emacs (make_fixnum (-1), Qnil);
}
else
{
@@ -1122,7 +1122,7 @@ command_loop (void)
/* End of file in -batch run causes exit here. */
if (noninteractive)
- Fkill_emacs (Qt);
+ Fkill_emacs (Qt, Qnil);
}
}
@@ -1331,7 +1331,7 @@ command_loop_1 (void)
Lisp_Object cmd;
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
/* Make sure the current window's buffer is selected. */
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
@@ -1402,7 +1402,7 @@ command_loop_1 (void)
/* A filter may have run while we were reading the input. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
set_buffer_internal (XBUFFER (XWINDOW (selected_window)->contents));
++num_input_keys;
@@ -1660,7 +1660,7 @@ read_menu_command (void)
unbind_to (count, Qnil);
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (i == 0 || i == -1)
return Qt;
@@ -2259,7 +2259,7 @@ read_event_from_main_queue (struct timespec *end_time,
/* Terminate Emacs in batch mode if at eof. */
if (noninteractive && FIXNUMP (c) && XFIXNUM (c) < 0)
- Fkill_emacs (make_fixnum (1));
+ Fkill_emacs (make_fixnum (1), Qnil);
if (FIXNUMP (c))
{
@@ -10039,7 +10039,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
if (fix_current_buffer)
{
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
if (XBUFFER (XWINDOW (selected_window)->contents)
!= current_buffer)
Fset_buffer (XWINDOW (selected_window)->contents);
@@ -10163,7 +10163,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
record_unwind_current_buffer ();
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
set_buffer_internal (XBUFFER (XWINDOW (window)->contents));
goto replay_sequence;
}
@@ -11393,7 +11393,7 @@ quit_throw_to_read_char (bool from_signal)
/* When not called from a signal handler it is safe to call
Lisp. */
if (!from_signal && EQ (Vquit_flag, Qkill_emacs))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
/* Prevent another signal from doing this before we finish. */
clear_waiting_for_input ();
diff --git a/src/xdisp.c b/src/xdisp.c
index 2dbc68f657c..a3a4338eb4f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12143,7 +12143,7 @@ setup_echo_area_for_printing (bool multibyte_p)
{
/* If we can't find an echo area any more, exit. */
if (! FRAME_LIVE_P (XFRAME (selected_frame)))
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
ensure_echo_area_buffers ();
diff --git a/src/xsmfns.c b/src/xsmfns.c
index 199e3ded3dd..7015a8eb633 100644
--- a/src/xsmfns.c
+++ b/src/xsmfns.c
@@ -522,7 +522,7 @@ Do not call this function yourself. */)
{
/* We should not do user interaction here, but it is not easy to
prevent. Fix this in next version. */
- Fkill_emacs (Qnil);
+ Fkill_emacs (Qnil, Qnil);
#if false
/* This will not be reached, but we want kill-emacs-hook to be run. */
diff --git a/src/xterm.c b/src/xterm.c
index 89dd28c0d58..ab4dcc3841a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -19773,7 +19773,7 @@ For details, see etc/PROBLEMS.\n",
if (terminal_list == 0)
{
fprintf (stderr, "%s\n", error_msg);
- Fkill_emacs (make_fixnum (70));
+ Fkill_emacs (make_fixnum (70), Qnil);
}
totally_unblock_input ();
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 42b09201de8..e4424f3cbed 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -263,7 +263,7 @@ form.")
nil))
(kill-emacs-args nil)
((symbol-function #'kill-emacs)
- (lambda (&optional arg) (push arg kill-emacs-args)))
+ (lambda (&optional arg arg) (push arg kill-emacs-args)))
(process
(make-process
:name "sleep"