Elisp'ten bir anahtar teslimi olayı nasıl simüle edebilirim?


26

Elisp'ten rastgele bir kilit olay simüle etmek mümkün mü? Belirli bir anahtar için bağlayıcı bulma yollarının farkındayım ve daha sonra etkileşimli olarak bu komutu çağırırım, ancak bu anahtar olayı bir komuta bağlı değilse?

Gibi bir örnekte , istediğim ne olur bağlamak C-`aynı davranmasına ESCanahtarın tüm bağlamlarda ?


key-bindingsAnahtar bağlama takma işlemini denemiyorsanız yanlış etiket gibi görünüyor . Ayrıca, belki de örneğinizi başka bir şeyle değiştirmelisiniz ki böylece kafanız karışmasın.
saat

@ b4hand Daha iyi etiketler için önerilere açığım. key-eventsEtiket yok . Bir tane yapmalı mıyım?
nispio

bana mantıklı geliyor, ancak bu, fare olaylarına da uygulanabileceği için olaylar daha iyi olabilir.
234

2
Elisp'te bir anahtar olayı simüle etmek isteyip istemediğiniz veya özellikle bir anahtar olarak başka bir anahtarmış gibi davranmak isteyip istemediğiniz konusunda kafam karışık mı ? key-translation-mapİkincisini kolaylaştırmaktan hoşlanıyor , bu yüzden tek istediğin buysa, daha fazla manuel bir şey yapmak yerine onu kullanmanızı öneririm.
phils

… ve eğer anahtar çeviri gerçekten burada ne istiyorsanız, bunun farklı bir soru olduğunu ve ayrı ayrı sormanız gerektiğini düşünüyorum; ve sonra bu soruna dair örneğinizi "elisp'te anahtar bir olayı nasıl simüle edebilirim?"
phils

Yanıtlar:


24

Komut döngüsüne rastgele olayları (tuş vuruşlarını, fare tıklamaları vb.) Koyarak onları besleyebilirsiniz unread-command-events. Örneğin, aşağıdakiler komut döngüsünün bir sonraki çalıştırılışında bir ara vermesine neden olur:

(setq unread-command-events (listify-key-sequence "\C-g"))

Bunun yalnızca olayları komut döngüsüne beslediğine dikkat edin, bu nedenle kendi kodunuzda dolaşıyorsanız ilginç hiçbir şey yapmaz.

Farkında olduğunuz farklı bir yaklaşım, verilen bir anahtarın bağlı olduğu işlevi bulmak ve kendiniz çalıştırmaktır:

(funcall (global-key-binding "\C-g"))

Bu hemen komutu yürütecek. Ancak, bazı komutların, varsayılan argümanlar gibi etkileşimli olarak çağrılıp çağrılmadıklarına bağlı olarak farklı davranışlara sahip olduklarına dikkat edin. Bunu kullanarak telafi etmek isteyeceksiniz call-interactively:

(call-interactively (global-key-binding "\C-g"))

Okudum unread-command-eventsama nasıl kullanılacağını çözemedim. Ayarlamanın benim için hiçbir etkisi olmadı. Nasıl kullanıldığına dair iyi bir örnek var mı?
nispio

Kullanıcının devam etmek için boşluk basmasını isterken kullandığını gördüm - kullanıcı başka bir şeye basarsa, devam eder unread-command-events.
JCH

@ nispio: unread-command-eventsSadece isminin söylediği şey. Bir etkinliği inceleyebilir ve ne olduğuna bağlı olarak koşullu olarak tekrar üzerine bastırarak u-c-enormal şekilde işlenebilirsiniz. Emacs kaynak kodunda kullanımıyla ilgili birçok örnek var - greparkadaşınız.
Drew

1
Elde edebildi unread-command-eventsişe. Daha önce özlediğim parça listify-key-sequencefonksiyondu. Ben sadece ham anahtar vektörünü kullanıyordum.
nispio

1
Bu cevap için teşekkürler. Tamamlama sistemimin etkileşimli olmayan testlerini uygulamak istedim, bu yüzden belirli bir anahtar sırasına izin verilen with-simulated-inputherhangi bir ifadeyi değerlendiren bir makro uygulamak için bu fikri kullandım unread-command-events: github.com/DarwinAwardWinner/ido-ubiquitous/blob/…
Ryan C. Thompson

8

Bildiğim en basit yol, sadece kullanmaktır execute-kbd-macro:

(defun foo () (interactive) (execute-kbd-macro (kbd "<escape>")))
(global-set-key (kbd "C-`") 'foo)

Yukarıdakilerin değerlendirilmesi ve daha sonra basılması C-` bana hata veriyor apply: Wrong number of arguments: #[(ad--addoit-function ....
nispio

1
@nispio Benim için değil. Bu hata bir öneriye benziyor.
Malabarba

@ Malabarba Sanırım haklısın. Taze başladıktan sonra emacs -Qbu hatayı mevcut değil. Yine de bu hatayı alıyorum:After 0 kbd macro iterations: foo: Lisp nesting exceeds `max-lisp-eval-depth'
nispio 23:14

Aslında aradığım şey buydu. Bazı garip bir nedenden dolayı (muhtemelen bazı etkileşim detayları ile evil), doğrudan istenen işlevi çağırmak benim durumumda beklenmeyen bir etki yarattı ( evilmi-jump-items) ve kullanmak zorunda kaldım(execute-kbd-macro (kbd "%"))
xji

4

Alındığı Bu yanıt , bu gibi küresel-set tuşunu kullanabilirsiniz

(global-set-key (kbd "C-`") (kbd "<escape>"))

Hangi C-`gibi davranacakescape

İkinci kombinasyon bir işlevi yerine getirmiyorsa, bunun bazı problemleri var gibi görünüyor. Eğer escapeböyle kullanılıyorsa Meta, o zaman düzgün çalışmıyor. Ancak fonksiyonlara bağlı komutlar için işe yaramış gibi görünüyor.


@nispio: Aslında, ikinci argüman dolaylı olarak bir klavye makrosuna dönüştürüldüğü için işe yarıyor.
shosti

1
@shosti basarak ardından yukarıdaki değerlendirilmesi ve C-` bana bir hata veriyor: After 0 kbd macro iterations: command-execute: Lisp nesting exceeds `max-lisp-eval-depth'.
nispio

@nispio: Muhtemelen zaten başka bir metoda C-bağlıydınız ESC, bu yüzden sonsuz bir döngüye giriyor.
shosti

@shosti Haklıydınız. eval-sexpBir seansta çok fazla insan oluyor. :-) Ama yine çalışıyor emacs -Qnedenler C-` basitçe hiçbir şey yapmak.
nispio

Sisteminize bağlı olarak (kbd "<escape>")ve (kbd "ESC")farklı şeyler ifade edebilir - ikisini de denediniz mi?
shosti

2

Jch’den kullanacağınız öneriyi okuduktan sonra unread-command-events, aradığım bazı şeyleri yapacak bir çözümü bir araya getirmeyi başardım.

(defun my-simulate-key-event (event &optional N)
  "Simulate an arbitrary keypress event.

This function sets the `unread-command-events' variable in order to simulate a
series of key events given by EVENT. Can also For negative N, simulate the
specified key EVENT directly.  For positive N, removes the last N elements from
the list of key events in `this-command-keys' and then appends EVENT.  For N nil,
treat as N=1."
  (let ((prefix (listify-key-sequence (this-command-keys)))
         (key (listify-key-sequence event))
         (n (prefix-numeric-value N)))
     (if (< n 0)
         (setq prefix key)
       (nbutlast prefix n)
       (nconc prefix key))
       (setq unread-command-events prefix)))

Hala çalışacak çok sayıda sapıklık var. Yani, bu işlevi tek bir satırda iki kez çağırırsam doğru sonucu alamam defun.


Kenar notu:

Phils'in kullanması önerisini inceledikten sonra key-translation-map, local-function-key-maphangisinin daha geniş hedeflerime ulaşmakta da çok yardımcı olduğunu buldum.

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.