emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master ca024b0: Add a new variable `inhibit-interaction'


From: Lars Ingebrigtsen
Subject: master ca024b0: Add a new variable `inhibit-interaction'
Date: Tue, 12 Jan 2021 09:12:45 -0500 (EST)

branch: master
commit ca024b0575c4ea754c4c6e6dbf21ed610e0d1fb8
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    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.
---
 doc/lispref/elisp.texi    |  1 +
 doc/lispref/errors.texi   |  5 +++++
 doc/lispref/minibuf.texi  | 33 +++++++++++++++++++++++++++++++++
 etc/NEWS                  |  6 ++++++
 src/data.c                |  3 +++
 src/lisp.h                |  1 +
 src/lread.c               | 23 +++++++++++++++++++----
 src/minibuf.c             | 29 ++++++++++++++++++++++++++++-
 test/src/lread-tests.el   |  6 ++++++
 test/src/minibuf-tests.el | 15 +++++++++++++++
 10 files changed, 117 insertions(+), 5 deletions(-)

diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index fa548b5..12255d1 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -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
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi
index 9ec1271..fb393b9 100644
--- a/doc/lispref/errors.texi
+++ b/doc/lispref/errors.texi
@@ -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.
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index d316c1f..0ce17ed 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -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
 
diff --git a/etc/NEWS b/etc/NEWS
index 28dffef..f2aa158 100644
--- a/etc/NEWS
+++ b/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.
 
diff --git a/src/data.c b/src/data.c
index d420bf5..35a6890 100644
--- a/src/data.c
+++ b/src/data.c
@@ -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");
diff --git a/src/lisp.h b/src/lisp.h
index 9d8dbbd..f658868 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -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.  */
 
diff --git a/src/lread.c b/src/lread.c
index 1ff0828..4b168fb 100644
--- a/src/lread.c
+++ b/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);
 
diff --git a/src/minibuf.c b/src/minibuf.c
index 868e481..5df1045 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -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);
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index edf8821..f2a60bc 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -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
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index b9cd255..28119fc 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]