Cuando parte de un defun,
(interactive "c(C)hoose (A)n (O)ption")
le pedirá al usuario un solo carácter; RETno es requerido. ¿Cómo puedo replicar este comportamiento de lectura sin la necesidad de hacerlo interactive?
Cuando parte de un defun,
(interactive "c(C)hoose (A)n (O)ption")
le pedirá al usuario un solo carácter; RETno es requerido. ¿Cómo puedo replicar este comportamiento de lectura sin la necesidad de hacerlo interactive?
Respuestas:
Además de las formas integradas para leer eventos individuales como read-chary read-char-exclusive, aquí hay una opción para leer un solo carácter, pero también especificar qué caracteres son de entrada aceptable:
(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)))
Por lo tanto, todo lo siguiente aceptará "C", "A" u "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))
Y aquí hay una forma de ejemplo de bucle para la entrada correcta en una responsevariable:
(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-choiceuno que lee uno de un conjunto de caracteres dado.
La pregunta fue respondida hace mucho tiempo, pero esta respuesta adicional puede proporcionar alguna ayuda a otros buscadores.
read-char-choicele permite especificar una lista de opciones. El fn no volverá hasta que el usuario seleccione una de esas opciones válidas.
(read-char-choice "prompt here (A, B, or C)? " '(?A ?B ?C))
En el caso degenerado en el que las opciones son simplemente Y o N (no distingue entre mayúsculas y minúsculas), existe y-or-n-p.
Ambos read-char-choicey y-or-n-pson rígidos, e insisten en una respuesta válida. En el primer caso, debe ser una de las opciones que especifique (como A, B o C en mi ejemplo), y en el último caso, debe ser Y o N. Si el usuario presiona Intro o cualquier otra tecla, y-or-n-pvolverá a preguntar. El read-char-choicesolo se sentará allí, en silencio. Ninguno de los dos proporciona una manera de devolver un valor predeterminado. Para obtener ese comportamiento, creo que debes construir tu propia interacción con read-charo read-key.
En mi experiencia, el problema con read-chary read-keysolo es que, si bien muestran la solicitud en el minibúfer, el cursor permanece en el búfer de edición principal. Esto es desorientador para el usuario y también es diferente al comportamiento de read-string.
Para evitar ESO, puede dejar que la variable cursor-in-echo-areaantes de llamar read-keymuestre el cursor en el minibúfer.
(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