aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Ingebrigtsen2021-01-12 15:12:28 +0100
committerLars Ingebrigtsen2021-01-12 15:12:38 +0100
commitca024b0575c4ea754c4c6e6dbf21ed610e0d1fb8 (patch)
tree4b87356a3d9a269d88a7d0a05b04afcba9b7074d
parentd191f1589b6d06221a58c8c4e6a6441b0a2a2e49 (diff)
downloademacs-ca024b0575c4ea754c4c6e6dbf21ed610e0d1fb8.tar.gz
emacs-ca024b0575c4ea754c4c6e6dbf21ed610e0d1fb8.zip
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.
-rw-r--r--doc/lispref/elisp.texi1
-rw-r--r--doc/lispref/errors.texi5
-rw-r--r--doc/lispref/minibuf.texi33
-rw-r--r--etc/NEWS6
-rw-r--r--src/data.c3
-rw-r--r--src/lisp.h1
-rw-r--r--src/lread.c23
-rw-r--r--src/minibuf.c29
-rw-r--r--test/src/lread-tests.el6
-rw-r--r--test/src/minibuf-tests.el15
10 files changed, 117 insertions, 5 deletions
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi
index fa548b503aa..12255d122f9 100644
--- a/doc/lispref/elisp.texi
+++ b/doc/lispref/elisp.texi
@@ -739,6 +739,7 @@ Minibuffers
739* Minibuffer Windows:: Operating on the special minibuffer windows. 739* Minibuffer Windows:: Operating on the special minibuffer windows.
740* Minibuffer Contents:: How such commands access the minibuffer text. 740* Minibuffer Contents:: How such commands access the minibuffer text.
741* Recursive Mini:: Whether recursive entry to minibuffer is allowed. 741* Recursive Mini:: Whether recursive entry to minibuffer is allowed.
742* Inhibiting Interaction:: Running Emacs when no interaction is possible.
742* Minibuffer Misc:: Various customization hooks and variables. 743* Minibuffer Misc:: Various customization hooks and variables.
743 744
744Completion 745Completion
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi
index 9ec12714991..fb393b951f1 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}.
230 230
231@item unknown-image-type 231@item unknown-image-type
232The message is @samp{Cannot determine image type}. @xref{Images}. 232The message is @samp{Cannot determine image type}. @xref{Images}.
233
234@item inhibited-interaction
235The message is @samp{User interaction while inhibited}. This error is
236signalled when @code{inhibit-interaction} is non-@code{nil} and a user
237interaction function (like @code{read-from-minibuffer}) is called.
233@end table 238@end table
234 239
235@ignore The following seem to be unused now. 240@ignore The following seem to be unused now.
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index d316c1f0602..0ce17ed571a 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -32,6 +32,7 @@ argument.
32* Minibuffer Windows:: Operating on the special minibuffer windows. 32* Minibuffer Windows:: Operating on the special minibuffer windows.
33* Minibuffer Contents:: How such commands access the minibuffer text. 33* Minibuffer Contents:: How such commands access the minibuffer text.
34* Recursive Mini:: Whether recursive entry to minibuffer is allowed. 34* Recursive Mini:: Whether recursive entry to minibuffer is allowed.
35* Inhibiting Interaction:: Running Emacs when no interaction is possible.
35* Minibuffer Misc:: Various customization hooks and variables. 36* Minibuffer Misc:: Various customization hooks and variables.
36@end menu 37@end menu
37 38
@@ -2617,6 +2618,38 @@ to @code{t} in the interactive declaration (@pxref{Using Interactive}).
2617The minibuffer command @code{next-matching-history-element} (normally 2618The minibuffer command @code{next-matching-history-element} (normally
2618@kbd{M-s} in the minibuffer) does the latter. 2619@kbd{M-s} in the minibuffer) does the latter.
2619 2620
2621@node Inhibiting Interaction
2622@section Inhibiting Interaction
2623
2624It's sometimes useful to be able to run Emacs as a headless server
2625process that responds to commands given over a network connection.
2626However, Emacs is primarily a platform for interactive usage, so many
2627commands prompt the user for feedback in certain anomalous situations.
2628This makes this use case more difficult, since the server process will
2629just hang waiting for user input.
2630
2631@vindex inhibit-interaction
2632Binding the @code{inhibit-interaction} variable to something
2633non-@code{nil} makes Emacs signal a @code{inhibited-interaction} error
2634instead of prompting, which can then be used by the server process to
2635handle these situations.
2636
2637Here's a typical use case:
2638
2639@lisp
2640(let ((inhibit-interaction t))
2641 (respond-to-client
2642 (condition-case err
2643 (my-client-handling-function)
2644 (inhibited-interaction err))))
2645@end lisp
2646
2647If @code{my-client-handling-function} ends up calling something that
2648asks the user for something (via @code{y-or-n-p} or
2649@code{read-from-minibuffer} or the like), an
2650@code{inhibited-interaction} error is signalled instead. The server
2651code then catches that error and reports it to the client.
2652
2620@node Minibuffer Misc 2653@node Minibuffer Misc
2621@section Minibuffer Miscellany 2654@section Minibuffer Miscellany
2622 2655
diff --git a/etc/NEWS b/etc/NEWS
index 28dffef73ac..f2aa158d9d6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1537,6 +1537,12 @@ that makes it a valid button.
1537 1537
1538** Miscellaneous 1538** Miscellaneous
1539 1539
1540+++
1541*** New variable 'inhibit-interaction' to make user prompts signal an error.
1542If this is bound to something non-nil, functions like
1543`read-from-minibuffer', `read-char' (and related) will signal an
1544`inhibited-interaction' error.
1545
1540--- 1546---
1541*** 'process-attributes' now works under OpenBSD, too. 1547*** 'process-attributes' now works under OpenBSD, too.
1542 1548
diff --git a/src/data.c b/src/data.c
index d420bf5fc58..35a6890b9bd 100644
--- a/src/data.c
+++ b/src/data.c
@@ -3760,6 +3760,7 @@ syms_of_data (void)
3760 DEFSYM (Qbuffer_read_only, "buffer-read-only"); 3760 DEFSYM (Qbuffer_read_only, "buffer-read-only");
3761 DEFSYM (Qtext_read_only, "text-read-only"); 3761 DEFSYM (Qtext_read_only, "text-read-only");
3762 DEFSYM (Qmark_inactive, "mark-inactive"); 3762 DEFSYM (Qmark_inactive, "mark-inactive");
3763 DEFSYM (Qinhibited_interaction, "inhibited-interaction");
3763 3764
3764 DEFSYM (Qlistp, "listp"); 3765 DEFSYM (Qlistp, "listp");
3765 DEFSYM (Qconsp, "consp"); 3766 DEFSYM (Qconsp, "consp");
@@ -3844,6 +3845,8 @@ syms_of_data (void)
3844 PUT_ERROR (Qbuffer_read_only, error_tail, "Buffer is read-only"); 3845 PUT_ERROR (Qbuffer_read_only, error_tail, "Buffer is read-only");
3845 PUT_ERROR (Qtext_read_only, pure_cons (Qbuffer_read_only, error_tail), 3846 PUT_ERROR (Qtext_read_only, pure_cons (Qbuffer_read_only, error_tail),
3846 "Text is read-only"); 3847 "Text is read-only");
3848 PUT_ERROR (Qinhibited_interaction, error_tail,
3849 "User interaction while inhibited");
3847 3850
3848 DEFSYM (Qrange_error, "range-error"); 3851 DEFSYM (Qrange_error, "range-error");
3849 DEFSYM (Qdomain_error, "domain-error"); 3852 DEFSYM (Qdomain_error, "domain-error");
diff --git a/src/lisp.h b/src/lisp.h
index 9d8dbbd629f..f6588685443 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4351,6 +4351,7 @@ extern EMACS_INT minibuf_level;
4351extern Lisp_Object get_minibuffer (EMACS_INT); 4351extern Lisp_Object get_minibuffer (EMACS_INT);
4352extern void init_minibuf_once (void); 4352extern void init_minibuf_once (void);
4353extern void syms_of_minibuf (void); 4353extern void syms_of_minibuf (void);
4354extern void barf_if_interaction_inhibited (void);
4354 4355
4355/* Defined in callint.c. */ 4356/* Defined in callint.c. */
4356 4357
diff --git a/src/lread.c b/src/lread.c
index 1ff0828e85e..4b168fb84bd 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -767,11 +767,16 @@ is used for reading a character.
767If the optional argument SECONDS is non-nil, it should be a number 767If the optional argument SECONDS is non-nil, it should be a number
768specifying the maximum number of seconds to wait for input. If no 768specifying the maximum number of seconds to wait for input. If no
769input arrives in that time, return nil. SECONDS may be a 769input arrives in that time, return nil. SECONDS may be a
770floating-point value. */) 770floating-point value.
771
772If `inhibit-interaction' is non-nil, this function will signal an
773`inhibited-interaction' error. */)
771 (Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds) 774 (Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
772{ 775{
773 Lisp_Object val; 776 Lisp_Object val;
774 777
778 barf_if_interaction_inhibited ();
779
775 if (! NILP (prompt)) 780 if (! NILP (prompt))
776 message_with_string ("%s", prompt, 0); 781 message_with_string ("%s", prompt, 0);
777 val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds); 782 val = read_filtered_event (1, 1, 1, ! NILP (inherit_input_method), seconds);
@@ -793,9 +798,14 @@ is used for reading a character.
793If the optional argument SECONDS is non-nil, it should be a number 798If the optional argument SECONDS is non-nil, it should be a number
794specifying the maximum number of seconds to wait for input. If no 799specifying the maximum number of seconds to wait for input. If no
795input arrives in that time, return nil. SECONDS may be a 800input arrives in that time, return nil. SECONDS may be a
796floating-point value. */) 801floating-point value.
802
803If `inhibit-interaction' is non-nil, this function will signal an
804`inhibited-interaction' error. */)
797 (Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds) 805 (Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
798{ 806{
807 barf_if_interaction_inhibited ();
808
799 if (! NILP (prompt)) 809 if (! NILP (prompt))
800 message_with_string ("%s", prompt, 0); 810 message_with_string ("%s", prompt, 0);
801 return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method), seconds); 811 return read_filtered_event (0, 0, 0, ! NILP (inherit_input_method), seconds);
@@ -822,11 +832,16 @@ is used for reading a character.
822If the optional argument SECONDS is non-nil, it should be a number 832If the optional argument SECONDS is non-nil, it should be a number
823specifying the maximum number of seconds to wait for input. If no 833specifying the maximum number of seconds to wait for input. If no
824input arrives in that time, return nil. SECONDS may be a 834input arrives in that time, return nil. SECONDS may be a
825floating-point value. */) 835floating-point value.
826 (Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds) 836
837If `inhibit-interaction' is non-nil, this function will signal an
838`inhibited-interaction' error. */)
839(Lisp_Object prompt, Lisp_Object inherit_input_method, Lisp_Object seconds)
827{ 840{
828 Lisp_Object val; 841 Lisp_Object val;
829 842
843 barf_if_interaction_inhibited ();
844
830 if (! NILP (prompt)) 845 if (! NILP (prompt))
831 message_with_string ("%s", prompt, 0); 846 message_with_string ("%s", prompt, 0);
832 847
diff --git a/src/minibuf.c b/src/minibuf.c
index 868e481f843..5df10453739 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1075,6 +1075,13 @@ read_minibuf_unwind (void)
1075} 1075}
1076 1076
1077 1077
1078void
1079barf_if_interaction_inhibited (void)
1080{
1081 if (inhibit_interaction)
1082 xsignal0 (Qinhibited_interaction);
1083}
1084
1078DEFUN ("read-from-minibuffer", Fread_from_minibuffer, 1085DEFUN ("read-from-minibuffer", Fread_from_minibuffer,
1079 Sread_from_minibuffer, 1, 7, 0, 1086 Sread_from_minibuffer, 1, 7, 0,
1080 doc: /* Read a string from the minibuffer, prompting with string PROMPT. 1087 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,
1119 then the string which is returned includes whatever text properties 1126 then the string which is returned includes whatever text properties
1120 were present in the minibuffer. Otherwise the value has no text properties. 1127 were present in the minibuffer. Otherwise the value has no text properties.
1121 1128
1129If `inhibit-interaction' is non-nil, this function will signal an
1130 `inhibited-interaction' error.
1131
1122The remainder of this documentation string describes the 1132The remainder of this documentation string describes the
1123INITIAL-CONTENTS argument in more detail. It is only relevant when 1133INITIAL-CONTENTS argument in more detail. It is only relevant when
1124studying existing code, or when HIST is a cons. If non-nil, 1134studying 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. */)
1134{ 1144{
1135 Lisp_Object histvar, histpos, val; 1145 Lisp_Object histvar, histpos, val;
1136 1146
1147 barf_if_interaction_inhibited ();
1148
1137 CHECK_STRING (prompt); 1149 CHECK_STRING (prompt);
1138 if (NILP (keymap)) 1150 if (NILP (keymap))
1139 keymap = Vminibuffer_local_map; 1151 keymap = Vminibuffer_local_map;
@@ -1207,11 +1219,17 @@ point positioned at the end, so that SPACE will accept the input.
1207\(Actually, INITIAL can also be a cons of a string and an integer. 1219\(Actually, INITIAL can also be a cons of a string and an integer.
1208Such values are treated as in `read-from-minibuffer', but are normally 1220Such values are treated as in `read-from-minibuffer', but are normally
1209not useful in this function.) 1221not useful in this function.)
1222
1210Third arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits 1223Third arg INHERIT-INPUT-METHOD, if non-nil, means the minibuffer inherits
1211the current input method and the setting of`enable-multibyte-characters'. */) 1224the current input method and the setting of`enable-multibyte-characters'.
1225
1226If `inhibit-interaction' is non-nil, this function will signal an
1227`inhibited-interaction' error. */)
1212 (Lisp_Object prompt, Lisp_Object initial, Lisp_Object inherit_input_method) 1228 (Lisp_Object prompt, Lisp_Object initial, Lisp_Object inherit_input_method)
1213{ 1229{
1214 CHECK_STRING (prompt); 1230 CHECK_STRING (prompt);
1231 barf_if_interaction_inhibited ();
1232
1215 return read_minibuf (Vminibuffer_local_ns_map, initial, prompt, 1233 return read_minibuf (Vminibuffer_local_ns_map, initial, prompt,
1216 0, Qminibuffer_history, make_fixnum (0), Qnil, 0, 1234 0, Qminibuffer_history, make_fixnum (0), Qnil, 0,
1217 !NILP (inherit_input_method)); 1235 !NILP (inherit_input_method));
@@ -2321,6 +2339,15 @@ This variable also overrides the default character that `read-passwd'
2321uses to hide passwords. */); 2339uses to hide passwords. */);
2322 Vread_hide_char = Qnil; 2340 Vread_hide_char = Qnil;
2323 2341
2342 DEFVAR_BOOL ("inhibit-interaction",
2343 inhibit_interaction,
2344 doc: /* Non-nil means any user interaction will signal an error.
2345This variable can be bound when user interaction can't be performed,
2346for instance when running a headless Emacs server. Functions like
2347`read-from-minibuffer' (and the like) will signal `inhibited-interaction'
2348instead. */);
2349 inhibit_interaction = 0;
2350
2324 defsubr (&Sactive_minibuffer_window); 2351 defsubr (&Sactive_minibuffer_window);
2325 defsubr (&Sset_minibuffer_window); 2352 defsubr (&Sset_minibuffer_window);
2326 defsubr (&Sread_from_minibuffer); 2353 defsubr (&Sread_from_minibuffer);
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index edf88214f97..f2a60bcf327 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -190,4 +190,10 @@ literals (Bug#20852)."
190(ert-deftest lread-circular-hash () 190(ert-deftest lread-circular-hash ()
191 (should-error (read "#s(hash-table data #0=(#0# . #0#))"))) 191 (should-error (read "#s(hash-table data #0=(#0# . #0#))")))
192 192
193(ert-deftest test-inhibit-interaction ()
194 (let ((inhibit-interaction t))
195 (should-error (read-char "foo: "))
196 (should-error (read-event "foo: "))
197 (should-error (read-char-exclusive "foo: "))))
198
193;;; lread-tests.el ends here 199;;; lread-tests.el ends here
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index b9cd255462d..28119fc999e 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -410,5 +410,20 @@
410 (should (equal (try-completion "baz" '("bAz" "baz")) 410 (should (equal (try-completion "baz" '("bAz" "baz"))
411 (try-completion "baz" '("baz" "bAz")))))) 411 (try-completion "baz" '("baz" "bAz"))))))
412 412
413(ert-deftest test-inhibit-interaction ()
414 (let ((inhibit-interaction t))
415 (should-error (read-from-minibuffer "foo: "))
416
417 (should-error (y-or-n-p "foo: "))
418 (should-error (yes-or-no-p "foo: "))
419 (should-error (read-blanks-no-input "foo: "))
420
421 ;; See that we get the expected error.
422 (should (eq (condition-case nil
423 (read-from-minibuffer "foo: ")
424 (inhibited-interaction 'inhibit)
425 (error nil))
426 'inhibit))))
427
413 428
414;;; minibuf-tests.el ends here 429;;; minibuf-tests.el ends here