Làm thế nào tôi có thể đọc một ký tự duy nhất từ ​​xe buýt nhỏ?


11

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; RETkhô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:


6

Thay vì read-chartôi đề nghị read-key. Sự khác biệt là read-keytuân theo tất cả các bản sửa lỗi thông thường như input-decode-map, và function-key-mapvì vậy nó sẽ hoạt động tốt trong một tty.


Được kết hợp với thông tin trong một câu trả lời khác , đây dường như là câu trả lời chính xác nhất cho câu hỏi được hỏi :) Nhận xét của glucas cung cấp một chức năng tốt :)read-char-choice
Sean Allred

5

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 responsebiế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)

2
Cũng có thể read-char-choiceđọc một trong các bộ ký tự đã cho.
glucas

@glucas: ah, các loại hạt, bạn nói đúng. Hình như tôi đã phát minh lại bánh xe.
Dan

4

call-interactivelylà những gì diễn giải các (interactive "cPROMPT")đặc điểm kỹ thuật, ctùy chọn được gửi đến read-char. Do đó, những điều sau đây nên hoạt động trong bối cảnh không tương tác:

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

3

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-choicecho 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-choicey-or-n-pcứ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-psẽ hỏi lại. Ý read-char-choicechí 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-charhoặc read-key.

Theo kinh nghiệm của tôi, vấn đề với read-charread-keymộ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-areatrướ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)))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.