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.
This commit is contained in:
Lars Ingebrigtsen 2022-04-17 13:37:51 +02:00
parent 0829c6836e
commit 5be9a9cacf
10 changed files with 68 additions and 25 deletions

View file

@ -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

View file

@ -194,6 +194,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
@ -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'.

View file

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

View file

@ -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

View file

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

View file

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

View file

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

View file

@ -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. */

View file

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

View file

@ -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"