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:
parent
0829c6836e
commit
5be9a9cacf
10 changed files with 68 additions and 25 deletions
|
@ -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
|
||||
|
|
12
etc/NEWS
12
etc/NEWS
|
@ -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'.
|
||||
|
|
|
@ -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.
|
||||
|
|
21
src/emacs.c
21
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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue