Làm thế nào để tôi viết một hàm `hoàn thành-tại-điểm-hàm 'đơn giản?


9

Tôi đang xem xét viết một chế độ chính để chỉnh sửa Magic: các sàn tập hợp.

Hầu hết có vẻ khá đơn giản nhưng tôi có một câu hỏi. Có khoảng 15 000 thẻ Magic duy nhất có sẵn (thẻ có tên duy nhất là). Tôi muốn có thể hoàn thành chống lại chúng bằng cách viết một hàm hoàn thành tại điểm. Tôi đã tìm kiếm một số ví dụ đơn giản, cơ bản về chức năng capf chỉ hoàn thành đối với một tập hợp các từ để làm cơ sở cho chế độ của tôi nhưng không tìm thấy gì cho đến nay. Bạn có biết bất kỳ ví dụ tốt cho việc này để bắt đầu? Và bạn có tin rằng sẽ dễ dàng có được hiệu suất tốt hay tôi sẽ phải viết cấu trúc dữ liệu của riêng mình (tôi có thể nghĩ giống như một Trie).

Rõ ràng là tôi cần tìm cách đồng bộ hóa với thẻ mới, v.v. và trong tương lai thậm chí có thể tìm kiếm thẻ theo các đặc điểm khác ngoài tên thẻ nhưng điều đó có thể chờ.

Câu trả lời:


17

Tài liệu

Việc hoàn thành API tại chức năng điểm có thể được tìm thấy trong tài liệu về completion-at-point-functions

Mỗi hàm trên hook này được gọi lần lượt mà không có bất kỳ đối số nào và sẽ trả về nil có nghĩa là nó không được áp dụng tại điểm hoặc một hàm không có đối số để thực hiện hoàn thành (không khuyến khích) hoặc danh sách biểu mẫu (START END THU . PROPS) trong đó START và END phân định thực thể cần hoàn thành và nên bao gồm điểm, THU THẬP là bảng hoàn thành để sử dụng để hoàn thành nó và PROPS là danh sách thuộc tính để biết thêm thông tin.

start, endpropsrõ ràng, nhưng tôi nghĩ định dạng của collectionkhông được xác định đúng. Cho rằng bạn có thể xem tài liệu của try-completionhoặcall-completions

Nếu THU THẬP là tồn tại, các phím (ô tô của các yếu tố) là sự hoàn thành có thể. Nếu một phần tử không phải là một ô khuyết điểm, thì chính phần tử đó là sự hoàn thành có thể. Nếu THU THẬP là bảng băm, tất cả các khóa là chuỗi hoặc ký hiệu là sự hoàn thành có thể. Nếu THU THẬP là một obarray, tên của tất cả các biểu tượng trong obarray là hoàn thành có thể.

THU THẬP cũng có thể là một chức năng để tự hoàn thành. Nó nhận được ba đối số: các giá trị CHUINGI, PREDICATE và nil. Bất cứ thứ gì nó trả về đều trở thành giá trị của 'hoàn thành thử'.

Thí dụ

Dưới đây là một ví dụ đơn giản về hoàn thành tại hàm điểm, sử dụng các từ được định nghĩa /etc/dictionaries-common/wordsđể hoàn thành các từ trong bộ đệm

(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))))))))

Hàm hoàn thành tìm từ tại điểm (thư viện thingatptđược sử dụng để tìm giới hạn của từ) và hoàn thành nó so với các từ trong /etc/dictionaries-common/wordstệp, thuộc tính :exclusiveđược đặt thành để noemacs có thể sử dụng các hàm capf khác nếu chúng ta thất bại. Cuối cùng, một số thuộc tính bổ sung được thiết lập để tăng cường tích hợp chế độ công ty.

Hiệu suất

Tệp từ trên hệ thống của tôi có 99171 mục và emacs có thể hoàn thành chúng mà không gặp vấn đề gì, vì vậy tôi đoán 15000 mục không phải là vấn đề.

Tích hợp với chế độ công ty

Chế độ công ty tích hợp rất tốt với completion-at-point-functionsviệc sử dụng company-capfphụ trợ, vì vậy nó sẽ hoạt động tốt cho bạn, nhưng bạn có thể tăng cường các hoàn thành do công ty cung cấp bằng cách trả lại bổ sung propstrong kết quả của chức năng capf. Các đạo cụ hiện đang được hỗ trợ là

:company-doc-buffer - Được sử dụng bởi công ty để hiển thị siêu dữ liệu cho ứng viên hiện tại

:company-docsig - Được sử dụng bởi công ty để lặp lại siêu dữ liệu về ứng cử viên trong xe buýt nhỏ

:company-location - Được sử dụng bởi công ty để nhảy đến vị trí của ứng cử viên hiện tại


Ôi trời! Cảm ơn câu trả lời thấu đáo! Tôi sẽ thử điều này một chút và sẽ chấp nhận sau đó. Cảm ơn thêm cho các gợi ý của Công ty (mà tôi thực sự đang sử dụng).
Mattias Bengtsson

Cảm ơn, điều đó thực sự hữu ích bây giờ tôi có thể định cấu hình hoàn thành tùy chỉnh một cách dễ dàng :)
clemera

Vui mừng tôi có thể giúp :)
Iqbal Ansari

0

@Iqbal Ansari đã đưa ra một câu trả lời tuyệt vời. Đây là một câu trả lời bổ sung, hy vọng nó sẽ giúp.

Đây là một triển khai sử dụng cơ chế hoàn thành cổ điển emacs, 2009.

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

Sau đây là mã thực hiện hoàn thành.

(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")))))

Sau đây là một triển khai sử dụng giao diện của chế độ ido. Đơn giản hơn nhiều.

(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)))

Bạn sẽ cần xác định xyz-kwdList là danh sách các từ của bạn.


2
-1 để phát minh lại giao diện hoàn thành theo cách tồi tệ hơn, tiếp nulltục notvà sử dụng các định danh camelcase và các biểu tượng Hy Lạp chỉ có ý nghĩa trong các chế độ của riêng bạn.
wasamasa

3
-1 vì không trả lời câu hỏi đó là gì completion-at-point-functions(tôi không đồng ý với @wasamasa về vấn đề nullvs not).
npostavs

3
@XahLee Các chức năng completion-at-point-functionsđược cho là trả về dữ liệu hoàn thành, không tự thực hiện hoàn thành. Vì vậy, các chức năng trong câu trả lời của bạn không thể sử dụng như các mục trong completion-at-point-functions.
npostavs

1
@npostavs ah tôi hiểu rồi. bạn đúng rồi. Cảm ơn!
Xah Lee

4
@npostavs Loại chức năng này vẫn sẽ hoạt động, nhưng thực sự việc viết một chức năng hoàn thành theo cách này là trái với giao diện tài liệu, và nó rất nản lòng.
Dmitry
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.