간단한 '완료 시점 함수'함수를 작성하려면 어떻게해야합니까?


9

매직 편집을위한 주요 모드 인 개더링 데크를 작성하려고합니다.

그것의 대부분은 매우 간단 해 보이지만 한 가지 질문이 있습니다. 약 15,000 개의 고유 한 매직 카드가 있습니다 (고유 이름이있는 카드). 시점 별 완성 기능을 작성하여 이에 대해 완료하고 싶습니다. 나는 내 모드를 기반으로하기 위해 단어 집합에 대해 완료되었지만 지금까지 아무것도 찾지 못한 capf 함수의 간단한 기본 예제를 찾고 있습니다. 이 작업을 시작하기위한 좋은 예를 알고 있습니까? 그리고 좋은 성능을 얻는 것이 쉬울 것이라고 생각하거나 내 데이터 구조를 작성해야한다고 생각하십니까 (나는 아마도 Trie처럼 생각하고 있습니다).

분명히 나는 ​​새로운 카드 등과 동기화 할 수있는 방법을 찾아야 할 것이며 나중에 카드 이름 이외의 다른 특성으로 카드를 검색 할 수도 있지만 기다릴 수 있습니다.

답변:


17

선적 서류 비치

포인트 함수에서의 API 완성은 다음의 문서에서 찾을 수 있습니다. completion-at-point-functions

이 후크의 각 함수는 인수없이 교대로 호출되며, 해당 시점에 적용 할 수 없음을 의미하기 위해 nil을 리턴하거나 완료 (감지 된)를 수행 할 인수가없는 함수 또는 양식 목록 (START END COLLECTION)을 리턴해야합니다. PROPS) START 및 END가 완료 할 엔티티를 구분하고 포인트를 포함해야하는 경우 COLLECTION은 완료하는 데 사용할 완료 테이블이고 PROPS는 추가 정보의 특성 목록입니다.

start, end그리고 props분명하다,하지만 난의 형식이 생각 collection제대로 정의되지 않았습니다. 이를 위해 try-completion또는 의 설명서를 볼 수 있습니다all-completions

COLLECTION이 목록 인 경우 키 (요소의 자동차)가 완료 될 수 있습니다. 요소가 죄수 셀이 아닌 경우 요소 자체가 가능한 완성입니다. COLLECTION이 해시 테이블 인 경우 문자열 또는 기호 인 모든 키가 가능한 완료입니다. COLLECTION이 obarray 인 경우 obarray의 모든 기호 이름이 완료 될 수 있습니다.

COLLECTION은 완료 자체를 수행하는 기능 일 수도 있습니다. 값 STRING, PREDICATE 및 nil의 세 가지 인수를받습니다. 그것이 리턴하는 것은`try-completion '의 가치가된다.

다음은 /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파일 의 단어에 대해 단어를 완성 합니다.이 속성 :exclusiveno실패한 경우 emacs가 다른 capf 함수를 사용할 수 있도록 설정됩니다 . 마지막으로 회사 모드 통합을 향상시키기 위해 일부 추가 속성이 설정됩니다.

공연

내 시스템의 단어 파일에는 99171 개의 항목이 있었고 emacs는 아무런 문제없이 완료 할 수 있었으므로 15000 개의 항목은 문제가되지 않아야합니다.

회사 모드와 통합

회사 모드 completion-at-point-functionscompany-capf백엔드 를 사용하는 것과 매우 잘 통합 되므로 즉시 사용할 수 있지만 propscapf 기능의 결과 로 추가 를 반환하여 회사가 제공하는 완성도를 향상시킬 수 있습니다 . 현재 지원되는 소품은

:company-doc-buffer -현재 후보에 대한 메타 데이터를 표시하기 위해 회사에서 사용

:company-docsig -회사에서 미니 버퍼에서 후보에 대한 메타 데이터를 에코하는 데 사용

:company-location -현재 후보자의 위치로 이동하기 위해 회사에서 사용


어머! 철저한 답변에 감사드립니다! 나는 이것을 조금 시도하고 그 후에 받아 들일 것이다. 회사 힌트 (실제로 사용하고 있음)에 대한 추가 감사.
Mattias Bengtsson

고마워, 그것은 정말 도움이 지금 커스텀 완성을 쉽게 구성 할 수 있습니다 :)
clemera

다행 나는 :) 도움이 될 수
이크발 안사리

0

@Iqbal Ansari가 큰 대답을하였습니다. 추가 답변이 있습니다. 도움이 되길 바랍니다.

다음은 2009 년 emacs classic 완료 메커니즘을 사용한 구현입니다.

;; 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-mode의 인터페이스를 사용한 구현입니다. 훨씬 간단합니다.

(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과 낙타 표기법 식별자 만 자신의 모드에서 의미가 그리스어 기호를 사용하여.
wasamasa

3
-1에 대해했던 질문에 대답하지 않는 completion-at-point-functions(I는 약 @wasamasa에 동의 nullnot것).
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.