ฉันจะอ่านตัวละครเดียวจาก minibuffer ได้อย่างไร


12

เมื่อส่วนหนึ่งของdefun,

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

จะให้ผู้ใช้ป้อนอักขระเดียว RETไม่จำเป็นต้องใช้. ฉันจะทำซ้ำพฤติกรรมการอ่านนี้โดยไม่จำเป็นต้องได้interactiveอย่างไร

คำตอบ:


7

มากกว่าผมขอแนะนำให้read-char read-keyข้อแตกต่างคือread-keyปฏิบัติตาม remappings ตามปกติทั้งหมดเช่นinput-decode-mapและfunction-key-mapดังนั้นจะทำงานอย่างถูกต้องใน tty


จับคู่กับข้อมูลในคำตอบอื่นดูเหมือนว่าจะเป็นคำตอบที่แม่นยำที่สุดสำหรับคำถามที่ถาม :) ความคิดเห็นของกลูกัสนั้นทำหน้าที่ได้ดี :)read-char-choice
Sean Allred

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 (กรณี insenstive) 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-charread-key

จากประสบการณ์ของผมมีปัญหากับread-charและread-keyคนเดียวคือในขณะที่พวกเขาแสดงพรอมต์ใน minibuffer ซากเคอร์เซอร์ในบัฟเฟอร์หลักสำหรับการแก้ไข read-stringนี่คือสับสนให้กับผู้ใช้และยังแตกต่างจากลักษณะการทำงานของ

เพื่อหลีกเลี่ยงปัญหานั้นคุณสามารถปล่อยให้ตัวแปรนั้นcursor-in-echo-areaก่อนที่จะเรียกread-keyเพื่อแสดงเคอร์เซอร์ใน minibuffer

(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)))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.