ฉันจะเขียนฟังก์ชั่น `เสร็จสิ้น ณ จุดฟังก์ชั่น 'ได้อย่างไร?


9

ฉันกำลังพิจารณาที่จะเขียนโหมดสำคัญสำหรับการแก้ไข Magic: The Gathering deck

ส่วนใหญ่ดูเหมือนจะค่อนข้างตรงไปตรงมา แต่ฉันมีหนึ่งคำถาม มีการ์ดเวทย์มนตร์ที่ไม่ซ้ำกันประมาณ 15,000 การ์ด (การ์ดที่มีชื่อเฉพาะ) ฉันต้องการที่จะเสร็จสมบูรณ์กับพวกเขาโดยการเขียนฟังก์ชั่นที่สมบูรณ์ที่จุดฟังก์ชั่น ฉันกำลังมองหาตัวอย่างง่ายๆพื้นฐานของฟังก์ชั่น capf ที่เพิ่งทำเสร็จกับชุดคำเพื่อยึดโหมดของฉัน แต่ยังไม่พบอะไรเลย คุณรู้ตัวอย่างที่ดีสำหรับการเริ่มต้นนี้หรือไม่? และคุณเชื่อหรือไม่ว่าจะเป็นเรื่องง่ายที่จะได้รับประสิทธิภาพที่ดีหรือฉันต้องเขียนโครงสร้างข้อมูลของตัวเอง (ฉันคิดว่าอาจเป็น Trie)

เห็นได้ชัดว่าฉันต้องหาวิธีซิงค์กับการ์ดใหม่ ฯลฯ และในอนาคตอาจจะสามารถค้นหาการ์ดด้วยคุณสมบัติอื่นนอกเหนือจากชื่อการ์ด แต่อาจรอได้

คำตอบ:


17

เอกสาร

ฟังก์ชัน API ที่จุดเสร็จสมบูรณ์สามารถดูได้ในเอกสารของ completion-at-point-functions

แต่ละฟังก์ชั่นของ hook นี้จะถูกเรียกใช้โดยไม่มีการโต้แย้งใด ๆ และควรคืนค่าให้เป็นศูนย์ซึ่งหมายความว่าไม่สามารถใช้งานได้ที่จุดหรือฟังก์ชั่นที่ไม่มีการโต้แย้งเพื่อดำเนินการให้เสร็จสิ้น (หมดกำลังใจ) หรือรายการแบบฟอร์ม . PROPS) ที่ START และ END กำหนดขอบเขตเอนทิตีให้เสร็จสมบูรณ์และควรมีจุด COLLECTION เป็นตารางความสมบูรณ์ที่จะใช้เพื่อทำให้เสร็จสมบูรณ์และ PROPS เป็นรายการคุณสมบัติสำหรับข้อมูลเพิ่มเติม

start, endและpropsที่เห็นได้ชัด แต่ฉันคิดว่ารูปแบบของการcollectionไม่ได้กำหนดไว้อย่างถูกต้อง เพื่อให้คุณสามารถดูเอกสารของtry-completionหรือall-completions

ถ้า COLLECTION เป็น alist คีย์ (รถยนต์ขององค์ประกอบ) คือความสำเร็จที่เป็นไปได้ หากองค์ประกอบนั้นไม่ใช่เซลล์ข้อเสียแสดงว่าองค์ประกอบนั้นเป็นความสมบูรณ์ที่เป็นไปได้ หาก COLLECTION เป็นแฮชตารางคีย์ทั้งหมดที่เป็นสตริงหรือสัญลักษณ์ล้วนเป็นความสำเร็จที่เป็นไปได้ ถ้า COLLECTION เป็น obarray ชื่อของสัญลักษณ์ทั้งหมดใน obarray นั้นเป็นความสมบูรณ์ที่เป็นไปได้

คอลเลคชั่นยังสามารถใช้เป็นฟังก์ชั่นในการทำให้เสร็จสมบูรณ์ได้ มันได้รับสามข้อโต้แย้ง: ค่า STRING, คาดการณ์และไม่มี อะไรก็ตามที่มันกลับมาจะกลายเป็นคุณค่าของ

ตัวอย่าง

ด้านล่างเป็นตัวอย่างง่ายๆของการทำให้สมบูรณ์ที่ฟังก์ชันจุดซึ่งใช้คำที่กำหนดใน/etc/dictionaries-common/wordsการเติมคำในบัฟเฟอร์ให้สมบูรณ์

(defvar words (split-string (with-temp-buffer
                              (insert-file-contents-literally "/etc/dictionaries-common/words")
                              (buffer-string))
                            "\n"))

(defun words-completion-at-point ()
  (let ((bounds (bounds-of-thing-at-point 'word)))
    (when bounds
      (list (car bounds)
            (cdr bounds)
            words
            :exclusive 'no
            :company-docsig #'identity
            :company-doc-buffer (lambda (cand)
                                  (company-doc-buffer (format "'%s' is defined in '/etc/dictionaries-common/words'" cand)))
            :company-location (lambda (cand)
                                (with-current-buffer (find-file-noselect "/etc/dictionaries-common/words")
                                  (goto-char (point-min))
                                  (cons (current-buffer) (search-forward cand nil t))))))))

ฟังก์ชั่นเสร็จสิ้นมองหาคำที่จุด (ห้องสมุดthingatptจะใช้ในการค้นหาขอบเขตของคำ) และเสร็จสิ้นกับคำใน/etc/dictionaries-common/wordsไฟล์คุณสมบัติ:exclusiveถูกตั้งค่าเพื่อnoให้ emacs สามารถใช้ฟังก์ชั่นอื่น ๆ ถ้าเราล้มเหลว ในที่สุดคุณสมบัติเพิ่มเติมบางอย่างถูกตั้งค่าเพื่อปรับปรุงการรวมโหมด บริษัท

ประสิทธิภาพ

ไฟล์ word ในระบบของฉันมี 99171 รายการและ emacs สามารถทำมันให้เสร็จโดยไม่มีปัญหาใด ๆ ดังนั้นฉันเดาว่า 15,000 รายการไม่น่าจะมีปัญหา

บูรณาการกับโหมด บริษัท

โหมด บริษัท ผสานรวมได้เป็นอย่างดีกับการcompletion-at-point-functionsใช้company-capfแบ็กเอนด์ดังนั้นจึงควรทำงานนอกกรอบให้คุณ แต่คุณสามารถปรับปรุงความสมบูรณ์ที่ บริษัท เสนอโดยส่งคืนเพิ่มเติมpropsในผลลัพธ์ของฟังก์ชัน capf อุปกรณ์ประกอบการสนับสนุนในปัจจุบันคือ

:company-doc-buffer - ใช้โดย บริษัท เพื่อแสดงข้อมูลเมตาสำหรับผู้สมัครปัจจุบัน

:company-docsig - ใช้โดย บริษัท เพื่อสะท้อนข้อมูลเมตาเกี่ยวกับผู้สมัครใน minibuffer

:company-location - ใช้โดย บริษัท เพื่อข้ามไปยังตำแหน่งของผู้สมัครปัจจุบัน


พุทโธ่! ขอบคุณสำหรับคำตอบอย่างละเอียด! ฉันจะลองดูสักเล็กน้อยแล้วจะยอมรับหลังจากนั้น ขอขอบคุณเป็นพิเศษสำหรับคำแนะนำของ บริษัท (ซึ่งฉันใช้งานจริง)
Mattias Bengtsson

ขอขอบคุณที่เป็นประโยชน์จริงๆตอนนี้ผมสามารถกำหนดค่าความสำเร็จที่กำหนดเองได้อย่างง่ายดาย :)
clemera

ดีใจที่ฉันสามารถช่วย :)
อิคบาลซารี

0

@Iqbal Ansari ให้คำตอบที่ดี นี่คือคำตอบเพิ่มเติมหวังว่ามันจะช่วยได้

นี่คือการใช้งานโดยใช้กลไกการเติมเต็ม emacs แบบคลาสสิกปี 2009

;; this is your lang's keywords
(setq xyz-kwdList
      '("touch"
       "touch_start"
       "touch_end"
       "for"
       "foreach"
       "forall"
       ))

ต่อไปนี้เป็นรหัสที่ทำให้เสร็จสมบูรณ์

(defun xyz-complete-symbol ()
  "Perform keyword completion on word before cursor."
  (interactive)
  (let ((posEnd (point))
        (meat (thing-at-point 'symbol))
        maxMatchResult)

    ;; when nil, set it to empty string, so user can see all lang's keywords.
    ;; if not done, try-completion on nil result lisp error.
    (when (not meat) (setq meat ""))
    (setq maxMatchResult (try-completion meat xyz-kwdList))

    (cond ((eq maxMatchResult t))
          ((null maxMatchResult)
           (message "Can't find completion for “%s”" meat)
           (ding))
          ((not (string= meat maxMatchResult))
           (delete-region (- posEnd (length meat)) posEnd)
           (insert maxMatchResult))
          (t (message "Making completion list…")
             (with-output-to-temp-buffer "*Completions*"
               (display-completion-list 
                (all-completions meat xyz-kwdList)
                meat))
             (message "Making completion list…%s" "done")))))

ติดตามการใช้งานโดยใช้ส่วนต่อประสานของโหมด ido ง่ายกว่ามาก

(defun abc-complete-symbol ()
  "Perform keyword completion on current symbol.
This uses `ido-mode' user interface for completion."
  (interactive)
  (let* (
         (bds (bounds-of-thing-at-point 'symbol))
         (p1 (car bds))
         (p2 (cdr bds))
         (current-sym
          (if  (or (null p1) (null p2) (equal p1 p2))
              ""
            (buffer-substring-no-properties p1 p2)))
         result-sym)
    (when (not current-sym) (setq current-sym ""))
    (setq result-sym
          (ido-completing-read "" xyz-kwdList nil nil current-sym ))
    (delete-region p1 p2)
    (insert result-sym)))

คุณจะต้องกำหนด xyz-kwdList เป็นรายการคำศัพท์ของคุณ


2
-1 สำหรับการสร้างอินเทอร์เฟซที่สมบูรณ์ในวิธีที่แย่กว่านั้นมากไปnullกว่านั้นnotและใช้ตัวระบุ camelcased และสัญลักษณ์กรีกที่เหมาะสมในโหมดของคุณเองเท่านั้น
wasamasa

3
-1 สำหรับการไม่ตอบคำถามซึ่งเกี่ยวกับcompletion-at-point-functions(ฉันไม่เห็นด้วยกับ @wasamasa เกี่ยวnullกับnotสิ่งvs )
npostavs

3
@XahLee ฟังก์ชั่นcompletion-at-point-functionsที่ควรจะส่งคืนข้อมูลความสมบูรณ์ไม่ใช่ดำเนินการเสร็จสิ้นด้วยตัวเอง completion-at-point-functionsดังนั้นฟังก์ชั่นในคำตอบของคุณจะไม่สามารถใช้งานได้เป็นรายการใน
npostavs

1
@npostavs อ่าฉันเห็น คุณพูดถูก ขอบคุณ!
Xah Lee

4
@npostavs ฟังก์ชั่นประเภทนี้ยังคงใช้งานได้ แต่แน่นอนว่าการเขียนฟังก์ชั่นเสร็จสิ้นด้วยวิธีนี้ขัดกับส่วนต่อประสานที่มีการบันทึกไว้และไม่แนะนำให้ใช้
Dmitry
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.