Basit bir “noktadan noktaya işlevler” işlevini nasıl yazarım?


9

Magic: The Gathering destelerini düzenlemek için büyük bir mod yazmayı düşünüyorum.

Çoğu oldukça basit görünüyor ama bir sorum var. Yaklaşık 15.000 benzersiz Magic kartı vardır (benzersiz isimlere sahip kartlar). Noktadan noktaya bir tamamlama işlevi yazarak onlara karşı tamamlayabilmek istiyorum. Ben sadece benim modu temel ama sadece bir şey bulmak için başarısız bir kelime kümesi karşı tamamlayan bir capf işlevi basit, temel bir örnek arıyordum. Başlamak için iyi bir örnek biliyor musunuz? İyi bir performans elde etmenin kolay olacağını mı yoksa kendi veri yapımı yazmak zorunda mı kalacağımı düşünüyor musunuz (belki bir Trie gibi düşünüyorum).

Açıkçası yeni kartlarla vb.

Yanıtlar:


17

belgeleme

Noktadaki API tamamlama işlevi, dokümantasyonunda bulunabilir. completion-at-point-functions

Bu kancadaki her işlev, herhangi bir argüman olmadan sırayla çağrılır ve noktaya uygulanamayacağı anlamına gelmesi için nil veya geri dönüşü olmayan (cesareti kırılmış) hiçbir argüman işlevi veya formun bir listesi (START END COLLECTION PROPS), START ve END öğelerinin tamamlanmasını sınırlandırdığı ve nokta içermesi gerektiğinde, KOLEKSİYON onu tamamlamak için kullanılacak tamamlama tablosudur ve PROPS ek bilgi için bir özellik listesidir.

start, endve propsaçıktır, ancak bence biçimi collectiondüzgün tanımlanmadı. Bunun için try-completionveyaall-completions

KOLEKSİYON bir elist ise, anahtarlar (elemanların arabaları) olası tamamlamalardır. Bir öğe eksilerini içermiyorsa, öğenin kendisi olası tamamlamadır. KOLEKSİYON bir karma tablo ise, dize veya simge olan tüm tuşlar olası tamamlamalardır. KOLEKSİYON bir obarray ise, obarray'deki tüm sembollerin isimleri olası tamamlamalardır.

KOLEKSİYON ayrıca tamamlamayı kendisi yapmak için bir işlev olabilir. Üç argüman alır: STRING, PREDICATE ve nil değerleri. Ne döndürürse döndürsün, 'tamamlama' değeri olur.

Misal

Aşağıda, /etc/dictionaries-common/wordsarabellekteki kelimeleri tamamlamak için tanımlanan kelimeleri kullanan nokta işlevindeki tamamlama işlemine basit bir örnek verilmiştir.

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

Tamamlama işlevi noktadaki kelimeyi arar (kütüphane thingatptkelimenin sınırlarını bulmak için kullanılır) ve /etc/dictionaries-common/wordsdosyadaki kelimelere karşı tamamlar ; özellik :exclusive, noemacs'ın başarısız olması durumunda diğer capf işlevlerini kullanabilmesi için ayarlanır . Son olarak, şirket modu entegrasyonunu geliştirmek için bazı ek özellikler ayarlanmıştır.

Verim

Sistemimdeki kelime dosyası 99171 girişe sahipti ve emacs bunları herhangi bir sorun olmadan tamamlayabildi, bu yüzden 15000 girişin bir sorun olmaması gerektiğini düşünüyorum.

Şirket modu ile entegrasyon

Şirket modu completion-at-point-functions, company-capfarka ucu kullanarak çok iyi bütünleşir , bu nedenle sizin için kutudan çıkarılmalıdır, ancak propscapf işlevi sonucunda ek olarak geri dönerek şirket tarafından sunulan tamamlamaları geliştirebilirsiniz . Şu anda desteklenen aksesuarlar

:company-doc-buffer - Şirket tarafından mevcut adayın meta verilerini görüntülemek için kullanılır

:company-docsig - Şirket tarafından minibuffer'daki aday hakkındaki meta verileri yankılamak için kullanılır

:company-location - Mevcut adayın yerine atlamak için şirket tarafından kullanılır


Aman! Ayrıntılı cevap için teşekkürler! Bunu biraz deneyeceğim ve bundan sonra kabul edeceğim. Şirket ipuçları için ekstra teşekkürler (ki aslında kullanıyorum).
Mattias Bengtsson

Teşekkürler, bu gerçekten yararlı şimdi kolayca özel tamamlamaları yapılandırabilirsiniz :)
clemera

Sevindim yardımcı olabilirim :)
Iqbal Ansari

0

@Iqbal Ansari harika bir cevap verdi. İşte ek bir cevap, umarım yardımcı olur.

İşte emacs classic tamamlama mekanizmasını kullanan bir uygulama, 2009.

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

Tamamlama işlemini yapan kod aşağıdadır.

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

Aşağıda ido-mode'un arayüzünü kullanan bir uygulama yer almaktadır. Çok daha basit.

(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'i kelimelerinizin bir listesi olarak tanımlamanız gerekir.


2
Tamamlama arayüzünü daha kötü bir şekilde yeniden keşfetmek, devam nulletmek notve sadece kendi modlarınızda mantıklı olan kamuflajlı tanımlayıcıları ve Yunan sembollerini kullanmak için -1.
wasamasa

3
-1 ile ilgili soruyu cevaplamadığınız için completion-at-point-functions( nullvs notşey hakkında @wasamasa ile katılmıyorum ).
npostavs

3
@XahLee içindeki işlevlerin completion-at-point-functionstamamlama verilerini döndürmesi gerekir, tamamlama işlemini kendileri gerçekleştirmezler. Dolayısıyla cevabınızdaki fonksiyonlar girişler olarak kullanılamaz completion-at-point-functions.
npostavs

1
@npostavs ah anlıyorum. Haklısın. Teşekkürler!
Xah Lee

4
@npostavs Bu tür bir işlev hala işe yarayacaktır, ancak aslında bu şekilde bir tamamlama işlevi yazmak belgelenen arayüze aykırıdır ve kesinlikle önerilmez.
Dmitry
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.