Khi một phần của defun
,
(interactive "c(C)hoose (A)n (O)ption")
sẽ nhắc người dùng cho một ký tự đơn; RET
không được yêu cầu. Làm thế nào tôi có thể sao chép hành vi đọc này mà không cần interactive
?
Khi một phần của defun
,
(interactive "c(C)hoose (A)n (O)ption")
sẽ nhắc người dùng cho một ký tự đơn; RET
không được yêu cầu. Làm thế nào tôi có thể sao chép hành vi đọc này mà không cần interactive
?
Câu trả lời:
Ngoài các cách tích hợp để đọc các sự kiện đơn lẻ như read-char
, và read-char-exclusive
đây là một tùy chọn để đọc một ký tự đơn lẻ, nhưng cũng chỉ định các ký tự nào được nhập vào chấp nhận:
(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)))
Vì vậy, tất cả những điều sau đây sẽ chấp nhận "C", "A" hoặc "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))
Và đây là một cách ví dụ để lặp cho đầu vào chính xác thành một response
biến:
(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
đọc một trong các bộ ký tự đã cho.
Câu hỏi đã được trả lời từ lâu, nhưng câu trả lời bổ sung này có thể cung cấp một số trợ giúp cho những người tìm kiếm khác.
read-char-choice
cho phép bạn chỉ định một danh sách các lựa chọn. Fn sẽ không trả về cho đến khi người dùng chọn một trong các tùy chọn hợp lệ đó.
(read-char-choice "prompt here (A, B, or C)? " '(?A ?B ?C))
Trong trường hợp suy biến trong đó các tùy chọn chỉ đơn giản là Y hoặc N (trường hợp không xác định), có y-or-n-p
.
Cả hai read-char-choice
và y-or-n-p
cứng nhắc, và nhấn mạnh vào một câu trả lời hợp lệ. Trong trường hợp trước, nó phải là một trong các tùy chọn bạn chỉ định (như A, B hoặc C trong ví dụ của tôi) và trong trường hợp sau, nó phải là Y hoặc N. Nếu người dùng nhấn enter hoặc bất kỳ phím nào khác, họ y-or-n-p
sẽ hỏi lại. Ý read-char-choice
chí chỉ ngồi đó, im lặng. Không cung cấp một cách để chỉ trả lại một mặc định. Để có được hành vi đó, tôi nghĩ bạn phải xây dựng sự tương tác của riêng mình với read-char
hoặc read-key
.
Theo kinh nghiệm của tôi, vấn đề với read-char
và read-key
một mình, là trong khi chúng hiển thị lời nhắc trong bộ thu nhỏ, con trỏ vẫn nằm trong bộ đệm chỉnh sửa chính. Điều này gây mất phương hướng cho người dùng, và cũng không giống như hành vi của read-string
.
Để tránh THAT, bạn có thể để biến cursor-in-echo-area
trước khi gọi read-key
để hiển thị con trỏ trong bộ thu nhỏ.
(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