mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Add a new variable `inhibit-interaction'
* doc/lispref/elisp.texi (Top): Add a link. * doc/lispref/errors.texi (Standard Errors): Mention the new error. * doc/lispref/minibuf.texi (Minibuffers): Add a link. (Inhibiting Interaction): New node. * src/data.c (syms_of_data): Define the `inhibited-interaction' error. * src/lisp.h: Export the barfing function. * src/lread.c (Fread_char, Fread_event, Fread_char_exclusive): Barf if inhibited. * src/minibuf.c (barf_if_interaction_inhibited): New function. (Fread_from_minibuffer, Fread_no_blanks_input): Barf if inhibited. (syms_of_minibuf): Define the `inhibit-interaction' variable.
This commit is contained in:
parent
d191f1589b
commit
ca024b0575
10 changed files with 117 additions and 5 deletions
|
|
@ -739,6 +739,7 @@ Minibuffers
|
|||
* Minibuffer Windows:: Operating on the special minibuffer windows.
|
||||
* Minibuffer Contents:: How such commands access the minibuffer text.
|
||||
* Recursive Mini:: Whether recursive entry to minibuffer is allowed.
|
||||
* Inhibiting Interaction:: Running Emacs when no interaction is possible.
|
||||
* Minibuffer Misc:: Various customization hooks and variables.
|
||||
|
||||
Completion
|
||||
|
|
|
|||
|
|
@ -230,6 +230,11 @@ The message is @samp{Wrong type argument}. @xref{Type Predicates}.
|
|||
|
||||
@item unknown-image-type
|
||||
The message is @samp{Cannot determine image type}. @xref{Images}.
|
||||
|
||||
@item inhibited-interaction
|
||||
The message is @samp{User interaction while inhibited}. This error is
|
||||
signalled when @code{inhibit-interaction} is non-@code{nil} and a user
|
||||
interaction function (like @code{read-from-minibuffer}) is called.
|
||||
@end table
|
||||
|
||||
@ignore The following seem to be unused now.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ argument.
|
|||
* Minibuffer Windows:: Operating on the special minibuffer windows.
|
||||
* Minibuffer Contents:: How such commands access the minibuffer text.
|
||||
* Recursive Mini:: Whether recursive entry to minibuffer is allowed.
|
||||
* Inhibiting Interaction:: Running Emacs when no interaction is possible.
|
||||
* Minibuffer Misc:: Various customization hooks and variables.
|
||||
@end menu
|
||||
|
||||
|
|
@ -2617,6 +2618,38 @@ to @code{t} in the interactive declaration (@pxref{Using Interactive}).
|
|||
The minibuffer command @code{next-matching-history-element} (normally
|
||||
@kbd{M-s} in the minibuffer) does the latter.
|
||||
|
||||
@node Inhibiting Interaction
|
||||
@section Inhibiting Interaction
|
||||
|
||||
It's sometimes useful to be able to run Emacs as a headless server
|
||||
process that responds to commands given over a network connection.
|
||||
However, Emacs is primarily a platform for interactive usage, so many
|
||||
commands prompt the user for feedback in certain anomalous situations.
|
||||
This makes this use case more difficult, since the server process will
|
||||
just hang waiting for user input.
|
||||
|
||||
@vindex inhibit-interaction
|
||||
Binding the @code{inhibit-interaction} variable to something
|
||||
non-@code{nil} makes Emacs signal a @code{inhibited-interaction} error
|
||||
instead of prompting, which can then be used by the server process to
|
||||
handle these situations.
|
||||
|
||||
Here's a typical use case:
|
||||
|
||||
@lisp
|
||||
(let ((inhibit-interaction t))
|
||||
(respond-to-client
|
||||
(condition-case err
|
||||
(my-client-handling-function)
|
||||
(inhibited-interaction err))))
|
||||
@end lisp
|
||||
|
||||
If @code{my-client-handling-function} ends up calling something that
|
||||
asks the user for something (via @code{y-or-n-p} or
|
||||
@code{read-from-minibuffer} or the like), an
|
||||
@code{inhibited-interaction} error is signalled instead. The server
|
||||
code then catches that error and reports it to the client.
|
||||
|
||||
@node Minibuffer Misc
|
||||
@section Minibuffer Miscellany
|
||||
|
||||
|
|
|
|||
6
etc/NEWS
6
etc/NEWS
|
|
@ -1537,6 +1537,12 @@ that makes it a valid button.
|
|||
|
||||
** Miscellaneous
|
||||
|
||||
+++
|
||||
*** New variable 'inhibit-interaction' to make user prompts signal an error.
|
||||
If this is bound to something non-nil, functions like
|
||||
`read-from-minibuffer', `read-char' (and related) will signal an
|
||||
`inhibited-interaction' error.
|
||||
|
||||
---
|
||||
*** 'process-attributes' now works under OpenBSD, too.
|
||||
|
||||
|
|
|
|||
|
|
@ -3760,6 +3760,7 @@ syms_of_data (void)
|
|||
DEFSYM (Qbuffer_read_only, "buffer-read-only");
|
||||
DEFSYM (Qtext_read_only, "text-read-only");
|
||||
DEFSYM (Qmark_inactive, "mark-inactive");
|
||||
DEFSYM (Qinhibited_interaction, "inhibited-interaction");
|
||||
|
||||
DEFSYM (Qlistp, "listp");
|
||||
DEFSYM (Qconsp, "consp");
|
||||
|
|
@ -3844,6 +3845,8 @@ syms_of_data (void)
|
|||
PUT_ERROR (Qbuffer_read_only, error_tail, "Buffer is read-only");
|
||||
PUT_ERROR (Qtext_read_only, pure_cons (Qbuffer_read_only, error_tail),
|
||||
"Text is read-only");
|
||||
PUT_ERROR (Qinhibited_interaction, error_tail,
|
||||
"User interaction while inhibited");
|
||||
|
||||
DEFSYM (Qrange_error, "range-error");
|
||||
DEFSYM (Qdomain_error, "domain-error");
|
||||
|
|
|
|||
|
|
@ -4351,6 +4351,7 @@ extern EMACS_INT minibuf_level;
|
|||
extern Lisp_Object get_minibuffer (EMACS_INT);
|
||||
extern void init_minibuf_once (void);
|
||||
extern void syms_of_minibuf (void);
|
||||
extern void barf_if_interaction_inhibited (void);
|
||||
|
||||
/* Defined in callint.c. */
|
||||
|
||||
|
|
|
|||
23
src/lread.c
23
src/lread.c
|
|
@ -767,11 +767,16 @@ is used for reading a character.
|
|||
If the optional argument SECONDS is non-nil, it should be a number
|
||||
specifying the maximum number of seconds to wait for input. If no
|
||||
input arrives in that time, return nil. SECONDS may be a
|
||||
floating-point value. */)
|
||||
floating-point value.
|
||||
|
||||
If `inhibit-interaction' is non-nil, this function will signal an
|
||||
`inhibited-interaction' error. */)
|
||||
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
|
||||
{
|
||||
Lisp_Object val;
|
||||
|
||||
barf_if_interaction_inhibited ();
|
||||
|
||||
if (! NILP (prompt))
|
||||
message_with_string ("%s", prompt, 0);
|
||||
val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds);
|
||||
|
|
@ -793,9 +798,14 @@ is used for reading a character.
|
|||
If the optional argument SECONDS is non-nil, it should be a number
|
||||
specifying the maximum number of seconds to wait for input. If no
|
||||
input arrives in that time, return nil. SECONDS may be a
|
||||
floating-point value. */)
|
||||
floating-point value.
|
||||
|
||||
If `inhibit-interaction' is non-nil, this function will signal an
|
||||
`inhibited-interaction' error. */)
|
||||
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
|
||||
{
|
||||
barf_if_interaction_inhibited ();
|
||||
|
||||
if (! NILP (prompt))
|
||||
message_with_string ("%s", prompt, 0);
|
||||
return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method), seconds);
|
||||
|
|
@ -822,11 +832,16 @@ is used for reading a character.
|
|||
If the optional argument SECONDS is non-nil, it should be a number
|
||||
specifying the maximum number of seconds to wait for input. If no
|
||||
input arrives in that time, return nil. SECONDS may be a
|
||||
floating-point value. */)
|
||||
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
|
||||
floating-point value.
|
||||
|
||||
If `inhibit-interaction' is non-nil, this function will signal an
|
||||
`inhibited-interaction' error. */)
|
||||
(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
|
||||
{
|
||||
Lisp_Object val;
|
||||
|
||||
barf_if_interaction_inhibited ();
|
||||
|
||||
if (! NILP (prompt))
|
||||
message_with_string ("%s", prompt, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -1075,6 +1075,13 @@ read_minibuf_unwind (void)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
barf_if_interaction_inhibited (void)
|
||||
{
|
||||
if (inhibit_interaction)
|
||||
xsignal0 (Qinhibited_interaction);
|
||||
}
|
||||
|
||||
DEFUN ("read-from-minibuffer", Fread_from_minibuffer,
|
||||
Sread_from_minibuffer, 1, 7, 0,
|
||||
doc: /* Read a string from the minibuffer, prompting with string PROMPT.
|
||||
|
|
@ -1119,6 +1126,9 @@ If the variable `minibuffer-allow-text-properties' is non-nil,
|
|||
then the string which is returned includes whatever text properties
|
||||
were present in the minibuffer. Otherwise the value has no text properties.
|
||||
|
||||
If `inhibit-interaction' is non-nil, this function will signal an
|
||||
`inhibited-interaction' error.
|
||||
|
||||
The remainder of this documentation string describes the
|
||||
INITIAL-CONTENTS argument in more detail. It is only relevant when
|
||||
studying existing code, or when HIST is a cons. If non-nil,
|
||||
|
|
@ -1134,6 +1144,8 @@ and some related functions, which use zero-indexing for POSITION. */)
|
|||
{
|
||||
Lisp_Object histvar, histpos, val;
|
||||
|
||||
barf_if_interaction_inhibited ();
|
||||
|
||||
CHECK_STRING (prompt);
|
||||
if (NILP (keymap))
|
||||
keymap = Vminibuffer_local_map;
|
||||
|
|
@ -1207,11 +1219,17 @@ point positioned at the end, so that SPACE will accept the input.
|
|||
\(Actually, INITIAL can also be a cons of a string and an integer.
|
||||
Such values are treated as in `read-from-minibuffer', but are normally
|
||||
not useful in this function.)
|
||||
|
||||
Third arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits
|
||||
the current input method and the setting of`enable-multibyte-characters'. */)
|
||||
the current input method and the setting of`enable-multibyte-characters'.
|
||||
|
||||
If `inhibit-interaction' is non-nil, this function will signal an
|
||||
`inhibited-interaction' error. */)
|
||||
(Lisp_Object prompt, Lisp_Object initial, Lisp_Object inherit_input_method)
|
||||
{
|
||||
CHECK_STRING (prompt);
|
||||
barf_if_interaction_inhibited ();
|
||||
|
||||
return read_minibuf (Vminibuffer_local_ns_map, initial, prompt,
|
||||
0, Qminibuffer_history, make_fixnum (0), Qnil, 0,
|
||||
!NILP (inherit_input_method));
|
||||
|
|
@ -2321,6 +2339,15 @@ This variable also overrides the default character that `read-passwd'
|
|||
uses to hide passwords. */);
|
||||
Vread_hide_char = Qnil;
|
||||
|
||||
DEFVAR_BOOL ("inhibit-interaction",
|
||||
inhibit_interaction,
|
||||
doc: /* Non-nil means any user interaction will signal an error.
|
||||
This variable can be bound when user interaction can't be performed,
|
||||
for instance when running a headless Emacs server. Functions like
|
||||
`read-from-minibuffer' (and the like) will signal `inhibited-interaction'
|
||||
instead. */);
|
||||
inhibit_interaction = 0;
|
||||
|
||||
defsubr (&Sactive_minibuffer_window);
|
||||
defsubr (&Sset_minibuffer_window);
|
||||
defsubr (&Sread_from_minibuffer);
|
||||
|
|
|
|||
|
|
@ -190,4 +190,10 @@ literals (Bug#20852)."
|
|||
(ert-deftest lread-circular-hash ()
|
||||
(should-error (read "#s(hash-table data #0=(#0# . #0#))")))
|
||||
|
||||
(ert-deftest test-inhibit-interaction ()
|
||||
(let ((inhibit-interaction t))
|
||||
(should-error (read-char "foo: "))
|
||||
(should-error (read-event "foo: "))
|
||||
(should-error (read-char-exclusive "foo: "))))
|
||||
|
||||
;;; lread-tests.el ends here
|
||||
|
|
|
|||
|
|
@ -410,5 +410,20 @@
|
|||
(should (equal (try-completion "baz" '("bAz" "baz"))
|
||||
(try-completion "baz" '("baz" "bAz"))))))
|
||||
|
||||
(ert-deftest test-inhibit-interaction ()
|
||||
(let ((inhibit-interaction t))
|
||||
(should-error (read-from-minibuffer "foo: "))
|
||||
|
||||
(should-error (y-or-n-p "foo: "))
|
||||
(should-error (yes-or-no-p "foo: "))
|
||||
(should-error (read-blanks-no-input "foo: "))
|
||||
|
||||
;; See that we get the expected error.
|
||||
(should (eq (condition-case nil
|
||||
(read-from-minibuffer "foo: ")
|
||||
(inhibited-interaction 'inhibit)
|
||||
(error nil))
|
||||
'inhibit))))
|
||||
|
||||
|
||||
;;; minibuf-tests.el ends here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue