Commit ca024b05 authored by Lars Ingebrigtsen's avatar Lars Ingebrigtsen

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.
parent d191f158
Pipeline #8665 passed with stage
in 48 minutes and 14 seconds
......@@ -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
......
......@@ -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. */
......
......@@ -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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment