[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/compat a18351d539 1/3: compat-26: Add read-answer
From: |
ELPA Syncer |
Subject: |
[elpa] externals/compat a18351d539 1/3: compat-26: Add read-answer |
Date: |
Sat, 21 Jan 2023 11:57:28 -0500 (EST) |
branch: externals/compat
commit a18351d539ac85ae31cd71520afff650ee5856b9
Author: Daniel Mendler <mail@daniel-mendler.de>
Commit: Daniel Mendler <mail@daniel-mendler.de>
compat-26: Add read-answer
---
NEWS.org | 1 +
compat-27.el | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
compat-tests.el | 19 +++++++++++++++++++
compat.texi | 45 +++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 119 insertions(+), 2 deletions(-)
diff --git a/NEWS.org b/NEWS.org
index f1d75124ec..ed6425d2a2 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -6,6 +6,7 @@
- compat-25: Add ~macroexp-parse-body~ and ~macroexp-quote~.
- compat-25: Add ~region-noncontiguous-p~.
- compat-25: Add ~save-mark-and-excursion~.
+- compat-26: Add ~read-answer~.
- compat-26: Add ~region-bounds~.
- compat-27: Add ~date-ordinal-to-time~.
- compat-27: Add ~major-mode-suspend~ and ~major-mode-restore~.
diff --git a/compat-27.el b/compat-27.el
index 0fad7943a7..8c06a5aabb 100644
--- a/compat-27.el
+++ b/compat-27.el
@@ -775,5 +775,61 @@ discarded."
(aset new-vec j (aref old-vec (mod (+ copy-hd j) old-size))))
(setcar ring 0))))))
+;;;; Defined in map-ynp.el
+
+(compat-declare-version "26.2")
+
+(compat-defvar read-answer-short 'auto ;; <compat-tests:read-answer>
+ "If non-nil, the `read-answer' function accepts single-character answers.
+If t, accept short (single key-press) answers to the question.
+If nil, require long answers. If `auto', accept short answers if
+`use-short-answers' is non-nil, or the function cell of `yes-or-no-p'
+is set to `y-or-n-p'.
+
+Note that this variable does not affect calls to the more
+commonly-used `yes-or-no-p' function; it only affects calls to
+the `read-answer' function. To control whether `yes-or-no-p'
+requires a long or a short answer, see the `use-short-answers'
+variable.")
+
+(compat-defun read-answer (question answers) ;; <compat-tests:read-answer>
+ "Read an answer either as a complete word or its character abbreviation.
+Ask user a question and accept an answer from the list of possible answers.
+
+QUESTION should end in a space; this function adds a list of answers to it.
+
+ANSWERS is an alist with elements in the following format:
+ (LONG-ANSWER SHORT-ANSWER HELP-MESSAGE)
+where
+ LONG-ANSWER is a complete answer,
+ SHORT-ANSWER is an abbreviated one-character answer,
+ HELP-MESSAGE is a string describing the meaning of the answer.
+
+SHORT-ANSWER is not necessarily a single character answer. It can be
+also a function key like F1, a character event such as C-M-h, or
+a control character like C-h.
+
+Example:
+ \\='((\"yes\" ?y \"perform the action\")
+ (\"no\" ?n \"skip to the next\")
+ (\"all\" ?! \"accept all remaining without more questions\")
+ (\"help\" ?h \"show help\")
+ (\"quit\" ?q \"exit\"))
+
+When `read-answer-short' is non-nil, accept short answers.
+
+Return a long answer even in case of accepting short ones.
+
+When `use-dialog-box' is t, pop up a dialog window to get user input."
+ ;; NOTE: For simplicity we provide a primitive implementation based on
+ ;; `read-multiple-choice', which does neither support long answers nor the
the
+ ;; gui dialog box.
+ (cadr (read-multiple-choice
+ (string-trim-right question)
+ (delq nil
+ (mapcar (lambda (x) (unless (equal "help" (car x))
+ (list (cadr x) (car x) (caddr x))))
+ answers)))))
+
(provide 'compat-27)
;;; compat-27.el ends here
diff --git a/compat-tests.el b/compat-tests.el
index bb22dbc0ad..431a7ffcc8 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -325,6 +325,25 @@
(setf (image-property image :width) nil)
(should-equal image '(image))))
+(ert-deftest read-answer ()
+ (let ((orig-re (symbol-function #'read-event))
+ (orig-rc (symbol-function #'read-char))
+ (orig-rm (symbol-function #'read-from-minibuffer)))
+ (unwind-protect
+ (dolist (test '(("Choose "
+ ("first" ?a "first description")
+ ("second" ?b "second description")
+ ("third" ?c))
+ ("Do it? " ("yes" ?y) ("no" ?n))))
+ (dolist (choice (cdr test))
+ (fset #'read-char (lambda (&rest _) (cadr choice)))
+ (fset #'read-event (lambda (&rest _) (cadr choice)))
+ (fset #'read-from-minibuffer (lambda (&rest _) (car choice)))
+ (should-equal (car choice) (read-answer (car test) (cdr test)))))
+ (fset #'read-event orig-re)
+ (fset #'read-char orig-rc)
+ (fset #'read-from-minibuffer orig-rm))))
+
(ert-deftest read-multiple-choice ()
(let ((orig-re (symbol-function #'read-event))
(orig-rc (symbol-function #'read-char))
diff --git a/compat.texi b/compat.texi
index 04b8d25788..60528cc3e5 100644
--- a/compat.texi
+++ b/compat.texi
@@ -556,6 +556,49 @@ The following functions and macros are implemented in Emacs
26.1. These functions are made available by Compat on Emacs versions
older than 26.1.
+@c copied from lispref/minibuf.texi
+@defun read-answer question answers
+This function prompts the user with text in @var{question}, which
+should end in the @samp{SPC} character. The function includes in the
+prompt the possible responses in @var{answers} by appending them to
+the end of @var{question}. The possible responses are provided in
+@var{answers} as an alist whose elements are of the following form:
+
+@lisp
+(@var{long-answer} @var{short-answer} @var{help-message})
+@end lisp
+
+@noindent
+where @var{long-answer} is the complete text of the user response, a
+string; @var{short-answer} is a short form of the same response, a
+single character or a function key; and @var{help-message} is the text
+that describes the meaning of the answer. If the variable
+@code{read-answer-short} is non-@code{nil}, the prompt will show the
+short variants of the possible answers and the user is expected to
+type the single characters/keys shown in the prompt; otherwise the
+prompt will show the long variants of the answers, and the user is
+expected to type the full text of one of the answers and end by
+pressing @key{RET}. If @code{use-dialog-box} is non-@code{nil}, and
+this function was invoked by mouse events, the question and the
+answers will be displayed in a GUI dialog box.
+
+The function returns the text of the @var{long-answer} selected by the
+user, regardless of whether long or short answers were shown in the
+prompt and typed by the user.
+
+Here is an example of using this function:
+
+@lisp
+(let ((read-answer-short t))
+ (read-answer "Foo "
+ '(("yes" ?y "perform the action")
+ ("no" ?n "skip to the next")
+ ("all" ?! "perform for the rest without more questions")
+ ("help" ?h "show help")
+ ("quit" ?q "exit"))))
+@end lisp
+@end defun
+
@c copied from lispref/functions.texi
@defun mapcan function sequence
This function applies @var{function} to each element of @var{sequence},
@@ -920,8 +963,6 @@ implemented in 26.1:
@itemize
@item
-The function @code{read-answer}.
-@item
The function @code{func-arity}.
@item
The function @code{secure-hash-algorithms}.