Elispからの任意のキーイベントをシミュレートするにはどうすればよいですか?


26

elispから任意のキーイベントをシミュレートすることは可能ですか?特定のキーのバインドを見つけて、そのコマンドを対話的に呼び出す方法を知っていますが、そのキーイベントがコマンドにバインドされていない場合はどうなりますか?

1例、私はバインドしたい場合C-`と同じ動作をするESCキーすべてのコンテキストでは


ように思えるkey-bindingsエイリアスへの結合キーをしようとしていない場合、間違ったタグです。また、混乱しないように、例を他の何かに変更する必要があります。
b4hand 14年

@ b4handより良いタグの提案を受け入れています。key-eventsタグはありません。作るべき?
nispio 14年

私には理にかなっているように聞こえますが、マウスイベントにも適用できるため、イベントの方が良いかもしれません。
b4hand 14年

2
elispでキーイベントをシミュレートするのか、それとも別のキーであるかのようにキーを動作させる機能が特に必要なのかについて、私はまだ混乱していますか?key-translation-map後者は、後者を促進するのが好きなので、それがあなたが望むすべてであるなら、私はそれ以上の何かをするよりもむしろそれを使うことを提案するでしょう。
フィル14年

...そして、キー翻訳が本当にあなたがここで望むものであるならば、私はそれが異なる質問だと思う、そしてあなたはそれを別々に尋ねるべきだと思う; そして、「elispで重要なイベントをシミュレートするにはどうすればよいか」というより一般的な問題により適切になるように、この質問の例を書き直します。
フィル14年

回答:


24

任意のイベント(キーストローク、マウスクリックなど)をコマンドループに送るには、それらをに配置しunread-command-eventsます。たとえば、次のコマンドループは、次回の実行時にブレークを実行します。

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

これはイベントをコマンドループにフィードするだけなので、独自のコードでループしている場合は何も面白くないことに注意してください。

あなたが知っていると思われる別のアプローチは、与えられたキーがバインドされている関数を見つけて、それを自分で実行することです:

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

これにより、コマンドがすぐに実行されます。ただし、一部のコマンドは、デフォルト引数など、対話的に呼び出されるかどうかによって動作が異なることに注意してください。あなたはそれを使用することによってそれを補償したいと思うでしょうcall-interactively

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

読みましたunread-command-eventsが、使用方法がわかりませんでした。設定しても効果がありません。使用方法の良い例はありますか?
nispio 14年

ユーザーがスペースを押して続行するように要求するときに使用されるのを見ました-ユーザーが何かを押すと、それがに進みますunread-command-events
jch 14年

@nispio:unread-command-eventsその名前のとおりです。イベントを調べて、それが何であるかに応じて、条件付きでイベントをプッシュバックしu-c-eて、正常に処理できるようにすることができます。Emacsソースコードでの使用例はたくさんあります- grepあなたの友達です。
ドリュー

1
unread-command-events仕事に就くことができました。私が前に行方不明だった部分はlistify-key-sequence機能だった。生のキーベクトルを使用していました。
nispio 14年

1
この答えをありがとう。私は実装にこのアイデアを使用して、私は、私の補完システムの非対話型のテストを実施したいwith-simulated-inputとの任意の式を評価するマクロunread-command-events指定したキー配列とLET結合:github.com/DarwinAwardWinner/ido-ubiquitous/blob/...を
ライアンC.トンプソン

8

私が知っている最も簡単な方法は、単に使用することexecute-kbd-macroです:

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

上記を評価してからを押すとC-` 、エラーが発生しますapply: Wrong number of arguments: #[(ad--addoit-function ...
nispio 14年

1
@nispio私のためではありません。そのエラーはアドバイスのように見えます。
マラバルバ14年

@Malabarbaあなたは正しいと思います。emacs -Qそのエラーで新たに開始した後は存在しません。それでもこのエラーは表示されます:After 0 kbd macro iterations: foo: Lisp nesting exceeds `max-lisp-eval-depth'
nispio 14年

これは実際に私が探していたものです。何らかの奇妙な理由(おそらくとの相互作用の詳細evil)のために、目的の関数を直接呼び出すと、私の場合(evilmi-jump-items)に予期しない影響があり、使用する必要がありました(execute-kbd-macro (kbd "%"))
xji

4

この答えから取った、あなたはこのようなグローバルセットキーを使用することができます

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

C-`として扱いますescape

ただし、2番目の組み合わせで関数が実行されない場合、これにはいくつかの問題があるようです。のescapeように使用されている場合Meta、正しく動作しません。ただし、関数にバインドされたコマンドでは機能するようです。


@nispio:実際には、2番目の引数が暗黙的にキーボードマクロに変換されるため、機能します。
shosti 14年

1
@shosti上記を評価してからを押すとC-` 、エラーが発生しますAfter 0 kbd macro iterations: command-execute: Lisp nesting exceeds `max-lisp-eval-depth'
nispio 14年

@nispio:おそらく他の方法でC-`にバインドさESCれているので、無限ループに入ります。
shosti 14年

@shostiあなたは正しかった。eval-sexp1つのセッションであまりにも多くのことが行われています。:-)しかし、単に何もしないようにemacs -Q原因で再試行しC-` ます。
nispio 14年

お使いのシステムに応じて、(kbd "<escape>")及び(kbd "ESC")異なるものを意味するかもしれない-あなたは両方を試してみましたか?
shosti 14年

2

jchから使用する提案を読んだ後unread-command-events、私が探しているもののいくつかを実行するソリューションを一緒にハックすることができました。

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

まだ解決すべきいくつかの問題があります。つまり、この関数をsingle内で連続して2回呼び出すと、正しい結果が得られませんdefun


サイドノート:

使用するフィルの提案をチェックした後、key-translation-map私はlocal-function-key-mapどちらがより広い目標のいくつかを達成するのに非常に役立つかを見つけることができました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.