Elisp에서 임의의 주요 이벤트를 어떻게 시뮬레이트 할 수 있습니까?


26

elisp에서 임의의 키 이벤트를 시뮬레이션 할 수 있습니까? 주어진 키에 대한 바인딩을 찾은 다음 해당 명령을 대화식으로 호출 할 수있는 방법을 알고 있지만 해당 키 이벤트가 명령에 바인딩되지 않은 경우 어떻게해야합니까?

하나의 예를 들어 , 내가 원하는 경우 어떻게 바인딩 C-`은 AS 같은 행동을 ESC의 모든 상황에서를 ?


key-bindings키 바인딩의 별칭을 지정하지 않으면 잘못된 태그 인 것 같습니다 . 또한 혼동되지 않도록 예제를 다른 것으로 변경해야 할 수도 있습니다.
b4hand

@ b4hand 나는 더 나은 태그를 제안합니다. key-events태그 가 없습니다 . 내가 만들어야 하나?
nispio

나에게는 합리적으로 들리지만, 마우스 이벤트에도 적용될 수 있기 때문에 이벤트가 더 나을 수 있습니다.
b4hand

2
나는 여전히 당신이 elisp에서 키 이벤트를 시뮬레이션 할 것인지를 혼동하고있어, 또는 당신은 특히 또 다른 핵심 인 것처럼 키 역할을 할 수있는 능력을 원한다? key-translation-map후자 는 촉진하기 때문에 좋아하는 것이라면 더 많은 수동 작업을 수행하는 대신 사용하는 것이 좋습니다.
phils

... 키 번역이 정말로 당신이 원하는 것이라면, 나는 그것이 다른 질문 이라고 생각하며 , 당신은 그것을 별도로 요구해야합니다. 그런 다음이 질문에 대한 예를 다시 말하면 "elisp에서 주요 이벤트를 어떻게 시뮬레이트합니까?"의보다 일반적인 문제에 더 적합합니다.
phils

답변:


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

사용자가 스페이스를 눌러 계속하도록 요청할 때 사용하는 것을 보았습니다. 사용자가 다른 것을 누르면 계속 진행 unread-command-events됩니다.
jch

@nispio : unread-command-events이름 그대로입니다. 이벤트를 검사 한 후 이벤트에 따라 조건부로 다시 밀어 넣어 u-c-e정상적으로 처리 될 수 있습니다. Emacs 소스 코드에는 그 사용 예가 많이 있습니다- grep당신의 친구입니다.
Drew

1
나는 unread-command-events일할 수 있었다 . 내가 놓친 부분은 listify-key-sequence기능이었습니다. 나는 원시 키 벡터를 사용하고있었습니다.
nispio

1
이 답변에 감사드립니다. 완성 시스템의 비 대화식 테스트를 구현하고 싶었으므로이 아이디어를 사용 하여 지정된 키 시퀀스에 바운드 바인딩 된 with-simulated-input식을 평가 하는 매크로 를 구현했습니다 unread-command-events. github.com/DarwinAwardWinner/ido-ubiquitous/blob/…
Ryan C. Thompson

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

1
@nispio 아닙니다. 그 오류는 조언처럼 보입니다.
Malabarba

@ Malabarba 당신이 옳다고 생각합니다. emacs -Q그 오류로 새로 시작한 후에 는 존재하지 않습니다. 그래도 여전히이 오류가 발생합니다.After 0 kbd macro iterations: foo: Lisp nesting exceeds `max-lisp-eval-depth'
nispio

이것은 실제로 내가 찾던 것입니다. 이상한 이유로 (아마도와의 상호 작용 세부 정보 evil) 원하는 함수를 직접 호출하면 예기치 않은 영향을 미쳤으며 (x evilmi-jump-items)(execute-kbd-macro (kbd "%"))
xji

4

이 답변 에서 가져온 것처럼 다음과 같이 전역 집합 키를 사용할 수 있습니다

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

어떤 취급 C-`으로escape

두 번째 조합이 함수를 실행하지 않으면 문제가있는 것 같습니다. 따라서 escape와 같이 사용 하면 Meta올바르게 작동하지 않습니다. 그러나 함수에 바인딩 된 명령에는 효과가있는 것 같습니다.


@nispio : 두 번째 인수는 암시 적으로 키보드 매크로로 변환되므로 실제로 작동합니다.
shosti

1
@shosti 위의 내용을 평가 한 다음를 누르면 C-` 오류가 발생 After 0 kbd macro iterations: command-execute: Lisp nesting exceeds `max-lisp-eval-depth'합니다..
nispio

@nispio : 아마도 이미 다른 방법으로 C-묶여 ESC있었기 때문에 무한 루프에 빠질 것입니다 .
shosti

@ shosti 당신이 맞아요. eval-sexp한 세션에 너무 많은 일이 발생합니다. :-) 그러나 다시 시도 emacs -Q하면 C-` 단순히 아무것도하지 않습니다.
nispio

시스템에 따라, (kbd "<escape>")그리고 (kbd "ESC")다른 것을 의미 할 수 있습니다 - 당신이 모두를 시도?
shosti

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 내의 행에서 두 번 호출하면 올바른 결과를 얻지 못합니다 defun.


사이드 노트 :

필자들의 사용 제안을 확인한 후 더 넓은 목표를 달성하는 데 도움이되는 key-translation-map것을 찾을 수있었습니다 local-function-key-map.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.