Як я можу прочитати одного символу з мінібуфера?


12

Коли частина а defun,

(interactive "c(C)hoose (A)n (O)ption")

підкаже користувачеві про один символ; RETне потрібно. Як я можу повторити цю поведінку читання без потреби interactive?

Відповіді:


7

Швидше ніж read-charя рекомендую read-key. Різниця полягає в тому, що вони read-keyпідпорядковуються всім звичайним доповненням, таким як input-decode-mapі function-key-map, тому вона буде працювати належним чином у tty.


У поєднанні з інформацією в іншій відповіді , здається, це найточніша відповідь на поставлене питання :) Хоча коментар glucas забезпечує хорошу функцію :)read-char-choice
Шон Аллред

5

Окрім вбудованих способів зчитування одиночних подій, таких як 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)

2
Є також, read-char-choiceякий читає один із заданого набору символів.
глюкас

@glucas: ах, горіхи, ти маєш рацію. Схоже, я винаходив колесо.
Дан

4

call-interactivelyце те, що інтерпретує (interactive "cPROMPT")специфікацію, на яку cнадсилається опція read-char. Тому в неінтерактивному контексті має працювати наступне:

(read-char "(C)hoose (A)n (O)ption")

3

На питання було дано відповідь, але ця додаткова відповідь може надати певну допомогу іншим шукачам.

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)))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.