Відповіді:
Окрім вбудованих способів зчитування одиночних подій, таких як read-char
та read-char-exclusive
, ось варіант для читання одного символу, а також вказати, які символи є прийнятними вхідними даними:
(defun read-char-picky (prompt chars &optional inherit-input-method seconds)
"Read characters like in `read-char-exclusive', but if input is
not one of CHARS, return nil. CHARS may be a list of characters,
single-character strings, or a string of characters."
(let ((chars (mapcar (lambda (x)
(if (characterp x) x (string-to-char x)))
(append chars nil)))
(char (read-char-exclusive prompt inherit-input-method seconds)))
(when (memq char chars)
char)))
Таким чином, усі наведені нижче дії приймуть або "C", "A", або "O":
(read-char-picky "(C)hoose (A)n (O)ption: " "CAO")
(read-char-picky "(C)hoose (A)n (O)ption: " '("C" "A" "O"))
(read-char-picky "(C)hoose (A)n (O)ption: " '(?C ?A ?O))
Ось приклад способу циклу правильного введення response
змінної:
(let (response)
(while (null (setq response
(read-char-picky "(C)hoose (A)n (O)ption: " "CAO")))
(message "Please pick one of \"C\", \"A\", or \"O\"!")
(sit-for .5))
response)
read-char-choice
який читає один із заданого набору символів.
На питання було дано відповідь, але ця додаткова відповідь може надати певну допомогу іншим шукачам.
read-char-choice
дозволяє вказати список варіантів. Fn не повернеться, поки користувач не вибере одну з цих дійсних опцій.
(read-char-choice "prompt here (A, B, or C)? " '(?A ?B ?C))
У виродженому випадку, коли варіанти просто Y або N (регістр нечутливий), існує y-or-n-p
.
Обидва read-char-choice
і y-or-n-p
жорсткі, і наполягають на правильній відповіді. У першому випадку він повинен бути одним із вказаних вами варіантів (наприклад, A, B або C у моєму прикладі), а в другому випадку він повинен бути Y або N. Якщо користувач натисне клавішу Enter або будь-яку іншу клавішу, y-or-n-p
запит знову запитається. read-char-choice
Буде просто сидіти, мовчати. Не передбачено способу просто повернути дефолт. Щоб отримати таку поведінку, я думаю, ви повинні побудувати власну взаємодію з read-char
або read-key
.
На мій досвід, проблема в тому read-char
і read-key
тому, що він відображає підказку в мінібуфері, курсор залишається в основному буфері редагування. Це дезорієнтує користувача, а також не відрізняється від поведінки read-string
.
Щоб уникнути ЦЕ, ви можете дозволити змінній cursor-in-echo-area
перед викликом read-key
відобразити курсор у мінібуфері.
(defun my-y-or-n-with-default (raw-prompt &optional default-yes)
"displays PROMPT in the minibuffer, prompts for a y or n,
returns t or nil accordingly. If neither Y or N is entered, then
if DEFAULT-YES, returns t, else nil."
(let* ((options-string (if default-yes "Y or n" "y or N"))
(prompt (concat raw-prompt "(" options-string ")? "))
(cursor-in-echo-area t)
(key (read-key (propertize prompt 'face 'minibuffer-prompt)))
(isyes (or (eq key ?y) (eq key ?Y)))
(isno (or (eq key ?n) (eq key ?N))))
(if (not (or isyes isno))
default-yes
isyes)))
read-char-choice