2013-04-18 37 views
5

Özel bir sekme tamamlama uygulaması yazmaya çalışıyorum; bu, noktanın nerede olduğuna bağlı olarak bir dizi farklı tamamlamayı dener. Ancak, tamamlanma koşullarının hiçbiri karşılanmazsa, mevcut modun yapması istenen her şeyi yapmak için sekmeyi tercih ederim. BöyleElisp: Koşullu olarak anahtarlamayı değiştir

şey:

(defun my-custom-tab-completion() 
    (interactive) 
    (cond 
    (some-condition 
    (do-something)) 
    (some-other-condition 
    (do-something-else)) 
    (t 
    (do-whatever-tab-is-supposed-to-do-in-the-current-mode))) ;; How do I do this? 

Şu anda belirli modlar için kontrol ve bu mod için doğru olanı yapıyor, ama gerçekten beni açıkça gerek kalmadan sadece sağ şeyi yapan bir çözüm istiyoruz ediyorum Bu özel mod için bir koşul ekleyin.

Bunu nasıl yapacağınıza dair herhangi bir fikir var mı?

Teşekkürler!/Erik

Aşağıdaki gibi key-binding (ya da daha spesifik varyantları global-key-binding, minor-mode-key-binding ve local-key-binding) bağlamaları için aktif keymaps prob fonksiyonlarını kullanabilir
+1

'tanımlar-key' ve 'yerel-set-key' belgelerine bakınız. Bu genellikle, mod özel anahtar eşlemesini değiştirerek yapılır. –

cevap

2

. Örneğin

: bakarken sonsuz döngüler önlemek için

(call-interactively (key-binding (kbd "TAB"))) 
;; in an emacs-lisp-mode buffer: 
;; --> indent-for-tab-command 
;; 
;; in a c++-mode buffer with yas/minor-mode: 
;; --> yas/expand 

Tek yön komut senin küçük bir modda bağlayıcı koymak ve geçici olarak tuş eşleşmesini devre dışı bırakmak olabilir TAB bağlıysa bağlayıcı TAB için:

(define-minor-mode my-complete-mode 
    "Smart completion" 
    :keymap (let ((map (make-sparse-keymap))) 
      (define-key map (kbd "TAB") 'my-complete) 
      map)) 

(defun my-complete() 
    (interactive) 
    (message "my-complete") 
    (let ((my-complete-mode nil)) 
    (call-interactively (key-binding (kbd "TAB"))))) 
+0

Cevabınız için teşekkürler! Buradaki problem, komutun sekmeye bağlanmasını sağlamaktır, bu yüzden tuş bağlaması aslında işlevin kendisini döndürür ve dolayısıyla sonsuz bir döngüye neden olur. Bir şekilde mod için "orijinal" anahtar haritasındaki bağa bakabilir miyim? –

+0

Haklısınız, bu kolayca yapılmaz. Olası bir geçici çözüm için düzenlememe bakın. – Francesco

+0

Küçük bir mod için, girişi "küçük mod-harita-alist" den kaldırmanız gerekmez: yalnızca küçük mod değişkenini (“tam-mod” olarak adlandırılır) aramanın etrafına yapıştırabilirsiniz 'anahtar-bağlama '. – Stefan

2

mümkün sen ulaşabileceğini Bu, herhangi bir özel çözüm olmaksızın. Çoğu modda TAB, yalnızca varsayılan olarak girinti yapar, ancak tab-always-indent genel değişkenini 'complete olarak ayarlarsanız, önce tamamlamayı dener ve tamamlama mümkün değilse girintilendirir. Bu genellikle çok iyi çalışır, ancak TAB ana modlarınızdan birinde başka bir komuta bağlı olsa da şansınız kalmaz.

İhtiyacınız olan modlarda çalışırsa, özel tamamlama işlevinizi tüm geçerli arabelleklerin (belki bir mod kancası kullanarak) listenin ön tarafına completion-at-point-functions önüne eklemeniz gerekir. completion-at-point komutu, completion-at-point-functions'da listelenen işlevlerden biri, nil değerini döndürene kadar çağırır, bu nedenle, özel tamamlama işlevinizin "düşmesi" için var olan tüm davranışların var olan davranışı nil döndürür.

Bu, soruya% 100 bir yanıt değildir, ancak birlikte çalıştığınız başlıca modlar normal yönergelere göre yazılırsa en temiz yol olabilir.

+0

Bu çok iyi bir nokta, ama birçok küçük mod, YASnippet gibi 'TAB' anahtarını veya örneğin otomatik tamamlamayı yeniden başlatabilir. Böyle küçük modların '(setq tab-always-indent' complete ') değerini onurlandırabileceğini biliyor musunuz? – Francesco

+0

Bu küçük modları geçersiz kılmak istiyorsanız, bunu yapın. Bunun için yine de 'for-ind-for-sekme-komutunu kullanabilirsiniz. BTW, tab "her zaman girintisi" nin "tam" değeri yasnippet ile çalışmazsa, bunu bir hata olarak (yasnippet'te) bildirmek isteyebilirsiniz. – Stefan

3

Koşullu olarak bir anahtar bağlama tanımlamak için Emacs key binding fallback dayalı bir makro yazdı. Bu belirtilen minör moduna keybinding ekler ancak koşul doğru değilse, önceden atanmış eylemi yürütülür:

(defmacro define-key-with-fallback (keymap key def condition &optional mode) 
    "Define key with fallback. Binds KEY to definition DEF in keymap KEYMAP, 
    the binding is active when the CONDITION is true. Otherwise turns MODE off 
    and re-enables previous definition for KEY. If MODE is nil, tries to recover 
    it by stripping off \"-map\" from KEYMAP name." 
    `(define-key ,keymap ,key 
    (lambda() (interactive) 
     (if ,condition ,def 
      (let* ((,(if mode mode 
        (let* ((keymap-str (symbol-name keymap)) 
          (mode-name-end (- (string-width keymap-str) 4))) 
         (if (string= "-map" (substring keymap-str mode-name-end)) 
          (intern (substring keymap-str 0 mode-name-end)) 
         (error "Could not deduce mode name from keymap name (\"-map\" missing?)")))) 
        nil) 
       (original-func (key-binding ,key))) 
      (call-interactively original-func)))))) 

Sonra ben sadece TAB için özel bağlama kullanmak için aşağıdaki gibi şeyler yapabilirsiniz Anahat-minör modda bir başlıkta.Aksi zaman varsayılan eylem (Ben girinti ve yasnippets ikisine de sahip) yürütülür:

(define-key-with-fallback outline-minor-mode-map (kbd "TAB") 
    (outline-cycle 1) (outline-on-heading-p)) 
3

BTW, burada başka bir çözümdür:

(define-key <map> <key> 
    `(menu-item "" <my-cmd> :filter ,(lambda (cmd) (if <my-predicate> cmd)))) 
+0

Bu numara beni defalarca kurtardı. –

0

define-key alıntı dize veya bu örnekteki gibi interaktif lambdas kabul edebilir.

Lambda, benim sekme tamamlanma gibi adlandırılmış işlevlerle değiştirilebilir ve daha etkili şekilde kullanılabilir. tanımlar-anahtarının docstringe (Emacs 25) kaynaktan

DEF is anything that can be a key's definition: 
nil (means key is undefined in this keymap), 
a command (a Lisp function suitable for interactive calling), 
a string (treated as a keyboard macro), 
a keymap (to define a prefix key), 
a symbol (when the key is looked up, the symbol will stand for its 
    function definition, which should at that time be one of the above, 
    or another symbol whose function definition is used, etc.), 
a cons (STRING . DEFN), meaning that DEFN is the definition 
    (DEFN should be a valid definition in its own right), 
or a cons (MAP . CHAR), meaning use definition of CHAR in keymap MAP, 
or an extended menu item definition. 
(See info node `(elisp)Extended Menu Items'.)