어떤 키맵에서 키가 바인딩되어 있는지 어떻게 알 수 있습니까?


63

에서 'd'키를 리바운드 gnus-article-mode했지만 포인트가 첨부 파일에있을 때 이전 동작이 계속 활성화됩니다. 리 바인딩은을 수행하여 적용되지 않았 음을 알 수 C-h k d있지만 그 시점에서 어떤 키 맵이 유효한지 알려주지 않아 리 바인드 할 수 있습니다.

그것을 찾는 방법이 있습니까?

다음은 정확한 예입니다. 악을 사용하고 있으며 기사가 동작 모드에 있기를 원합니다. 키보드 레이아웃을 위해 'd'를 키로 구성했습니다.

(evil-mode 1)
(add-to-list 'evil-motion-state-modes 'gnus-article-mode)
(setq evil-emacs-state-modes (remove 'gnus-article-mode evil-emacs-state-modes))
(define-key evil-motion-state-map "d" 'evil-previous-line)

사악한 키를 고려하기 위해 로컬 맵에서 gnus 키를 설정 해제했습니다.

(defun as/alter-article-evil-map ()
  (local-unset-key "d"))
(add-hook 'gnus-article-mode-hook 'as/alter-article-evil-map)

불행히도 포인트가 첨부 파일에 있으면 'd'키가 더 이상 올라가지 않지만 첨부 파일을 삭제할 수 있습니다. 나는 그 시점에서 다른 바인딩이 활성화되어 있다고 생각합니다.

솔루션 내가 사용하는 keymaps-at-point텍스트 속성에서였다 사용되는 키 맵을 보려면 아래를. 그런 다음 바운드 함수의 코드를보고 키맵의 이름을 찾았습니다 gnus-mime-button-map. 다음 코드는 내가 원하는 것을 수행합니다.

(defun as/alter-article-evil-map ()
  (define-key gnus-mime-button-map "d" nil))
(add-hook 'gnus-article-mode-hook 'as/alter-article-evil-map)

3
이 의사 코드 리스프와 설명을 Emacs가 키를 찾는 방법에 대한 고급 안내서로 사용하십시오Searching Keymaps : Elisp manual, node . 또한 노드를 참조 Functions for Key Lookup하고 Active Keymaps.
Drew

두 번째 기능에서 초기 답변에 꽤 큰 버그가있었습니다. 방금 수정 했으므로 키 바인드를 찾을 수 있습니다. 다시 시도해 주시겠습니까?
Malabarba

답변:


61

이맥스 25

주석에서 @YoungFrog가 언급 한 것처럼 Emacs 25.1부터C-h k 키 바인드를 설명하는 오래된 방법은 키가 발견 된 키 맵을 알려줍니다.

이맥스 이전 25

여기 에 몇 가지 코드가 있지만 모든 것을 다루지는 않으므로 불완전합니다. 아래는 개선 된 버전입니다.

키는 9 (!) 방식으로 바인딩 될 수 있습니다. 덕분에 대해 @ 드류하는 링크 (또한 보충 전체 목록). 우선 순위에 따라 다음과 같습니다.

  1. 키의 단자 별 집합 overriding-terminal-local-map. 이것은 set-transient-map함수에 의해 정의됩니다 .
  2. 버퍼 - 지방 재정의지도 overriding-local-map. 이 항목을 설정하면 항목 3–8을 건너 뜁니다 (아마도 이러한 항목이 많이 표시되지 않는 이유).
  3. keymap텍스트 전문성을 통한 시점 (실제 텍스트 또는 오버레이로 진행될 수 있음)
  4. 서로 다른 가능한 활성화 된 마이너 모드 세트를 시뮬레이트하는 변수 emulation-mode-map-alists.
  5. 주요 모드가 보조 모드의 키 바인드를 대체 할 수있는 변수 minor-mode-overriding-map-alist.
  6. 키 바인드가에 저장된 실제 마이너 모드minor-mode-map-alist .
  7. local-map텍스트 속성을 통해 (다시) 지점에서 . 이 항목이 있으면 항목 8을 건너 뜁니다.
  8. 표준 완충액 로컬 키맵 함수에 의해 리턴 (주요 모드 또는 로컬 버퍼 keybinds 간다) current-local-map.
  9. 에 의해 반환되는 전역 키맵current-global-map .

반 항목 10도 있습니다. 위의 절차를 통해 찾은 명령은 모두 다시 매핑되었을 수 있습니다.

다음 함수 는 이러한 가능성 중 일부 (가장 가능성이 높은 가능성)를 쿼리 하여 결과를 반환하거나 인쇄합니다.

(defun locate-key-binding (key)
  "Determine in which keymap KEY is defined."
  (interactive "kPress key: ")
  (let ((ret
         (list
          (key-binding-at-point key)
          (minor-mode-key-binding key)
          (local-key-binding key)
          (global-key-binding key))))
    (when (called-interactively-p 'any)
      (message "At Point: %s\nMinor-mode: %s\nLocal: %s\nGlobal: %s"
               (or (nth 0 ret) "") 
               (or (mapconcat (lambda (x) (format "%s: %s" (car x) (cdr x)))
                              (nth 1 ret) "\n             ")
                   "")
               (or (nth 2 ret) "")
               (or (nth 3 ret) "")))
    ret))

첫 번째를 제외하고 각각에 대해 내장 함수가 있으므로 하나를 작성해야합니다 (또한 위에 링크 된 코드의 개선 된 버전).

(defun key-binding-at-point (key)
  (mapcar (lambda (keymap) (when (keymapp keymap)
                             (lookup-key keymap key)))
          (list
           ;; More likely
           (get-text-property (point) 'keymap)
           (mapcar (lambda (overlay)
                     (overlay-get overlay 'keymap))
                   (overlays-at (point)))
           ;; Less likely
           (get-text-property (point) 'local-map)
           (mapcar (lambda (overlay)
                     (overlay-get overlay 'local-map))
                   (overlays-at (point))))))

포인트가 첨부 파일에있을 때 동작이 활성화되었다고 말하고 있기 때문에이 키 바인드가 오버레이 또는 텍스트 속성에서 발생할 가능성이 높습니다.

그래도 작동하지 않으면 다음 명령도 시도하십시오. 첨부 파일에 커서를 놓고 수행하십시오 M-x keymaps-at-point.

(defun keymaps-at-point ()
  "List entire keymaps present at point."
  (interactive)
  (let ((map-list
         (list
          (mapcar (lambda (overlay)
                    (overlay-get overlay 'keymap))
                  (overlays-at (point)))
          (mapcar (lambda (overlay)
                    (overlay-get overlay 'local-map))
                  (overlays-at (point)))
          (get-text-property (point) 'keymap)
          (get-text-property (point) 'local-map))))
    (apply #'message
           (concat 
            "Overlay keymap: %s\n"
            "Overlay local-map: %s\n"
            "Text-property keymap: %s\n"
            "Text-property local-map: %s")
           map-list)))

키에 로컬 바인딩이 있는지와 어떤 명령이 바인딩되어 있는지 알려 주지만 여전히 키맵이름을 알려주지는 않습니다 .
nispio

@nispio 로컬 바인딩이있는 경우 메이저 모드 키맵 또는 local-set-key 호출에서 가져와야합니다. 불행히도, 두 경우를 구별 할 수있는 확실한 방법은 없습니다.
Malabarba

1
@Malabarba "안타깝게도 두 사례를 구분할 수있는 쉬운 방법이 없습니까?" 분명히 정보가 모두 있습니다. 또한 모든 주요 모드에는 정확히 하나의 모드 맵이 있습니까? 그렇지 않은 경우 어떤 주 모드 맵이 활성화되어 있는지 알 수있는 방법이 있습니까?
nispio

1
아직 출시되지 않은 이맥스 25에서 시작하여, "Ch k"는 어떤 키맵이 주어진 키 바인딩이 어떤 키맵 (보다 정확하게는 : 키맵을 그 값으로 보유하는 심볼)인지 알려줍니다. 한정된. 출력 예 :k runs the command gnus-summary-kill-same-subject-and-select (found in gnus-summary-mode-map), which is (...)
YoungFrog

2
관심있는 사람이라면 누구나 키 바인딩의 키맵을 emacs 25+에 표시하는 관련 커밋 이 있습니다.
Kaushal Modi

2

그것에 대해 :

(defun my-lookup-key (key)
  "Search for KEY in all known keymaps."
  (mapatoms (lambda (ob) (when (and (boundp ob) (keymapp (symbol-value ob)))
                      (when (functionp (lookup-key (symbol-value ob) key))
                        (message "%S" ob))))
            obarray))

예를 들어 버퍼 (my-lookup-key (kbd "C-c v v"))목록을 얻는 경우 *Message*:

global-map
term-pager-break-map
widget-global-map

이 방법은 다음과 같은 출력과 같이 상위 키맵에 포함 된 하위 키맵을 검색하는 데 유용합니다.

(my-lookup-key (kbd "d"))

vc-prefix-map포함되어 있습니다 global-map:

(eq (lookup-key global-map (kbd "C-x v")) 'vc-prefix-map)

필터링 조건을 포함하도록 수정 keymapp하면 접두사를 검색 할 수 있습니다.

(defun my-lookup-key-prefix (key)
  "Search for KEY as prefix in all known keymaps."
  (mapatoms (lambda (ob) (when (and (boundp ob) (keymapp (symbol-value ob)))
                      (when (let ((m (lookup-key (symbol-value ob) key)))
                              (and m (or (symbolp m) (keymapp m))))
                        (message "%S" ob))))
            obarray))

그래서 rst-mode-map모두에서 찾을 수 :

(my-lookup-key-prefix (kbd "C-c C-t"))
(my-lookup-key-prefix (kbd "C-c C-t C-t"))

1

다음은 어떤 키 맵을 찾을 수 있습니까?에 대한 질문에 답하지는 않지만 이 경우 d사용자가 원하는 것에 따라 키가 작동하는지 확인하는 기본 문제를 처리합니다 . 원하는 경우이 답변을 삭제하고 해당 문제와 관련된 다른 질문 + 답변으로 전환 할 수 있습니다.

text-property/overlay지도 를 재정의하는 방법으로 다음을 사용할 수 있습니다.

(let ((map (make-sparse-keymap)))
  (define-key map "d" 'evil-previous-line)
  (setq overriding-local-map map))

당으로 활동지도 제어 , overriding-local-map이외의 다른 모든 활동지도보다 우선합니다 overriding-terminal-local-map.


더 이상 요약 모드에서 메시지를 열 수 없으며 악과 고드름이 작동하지 않습니다.
brab November

더 이상 요약 모드에서 메시지를 열 수 없으며 악과 고드름이 작동하지 않습니다.
Emily Hoover

0

emacs-buttonsbuttons-display접두사 인수와 함께 모든 현재 바인딩의 재귀 시각화를 표시합니다.

(면책 조항 : 나는 패키지의 저자입니다)

https://github.com/erjoalgo/emacs-buttons/blob/master/doc/img/sample-visualization.png

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