Как узнать, что на самом деле делает последовательность клавиш

14

Время от времени я наблюдаю неожиданное поведение при редактировании текста. Мой первый C-h kвыход - обычно использовать, чтобы узнать, какие функции вызываются данной последовательностью клавиш. Однако иногда документация расходится с наблюдаемым поведением. В этих случаях я обычно предполагаю, что какой-то другой пакет подключился к этой функции или последовательности клавиш и изменяет свое поведение.

Как я могу узнать, какие функции подключаются к моей последовательности клавиш?

Один из примеров, с которым я недавно столкнулся, это то, что я нажал "клавишу, и кавычки были вставлены в начало и конец активной области. У меня было подозрение, что это не было поведением Emacs по умолчанию, поэтому я обычно C-h k "выяснял, какая функция на самом деле вызывается.

В describe-keyдокументации сказано self-insert-command, что вызывается функция , которая является встроенной функцией. Короче говоря, после некоторого количества проб и ошибок я смог определить, чем вызвано поведение electric-pair-mode. Есть ли в будущем более быстрый способ прийти к такому выводу, чем отключать подозрительные пакеты по одному, пока не будет найден виновник?

nispio
источник
Возможно ли, что он electric-pair-modeбыл активирован только в некоторых основных режимах? Вы все еще видите self-insert-commandдля "когда вы делаете в C-h kто время как electric-pair-modeактивен?
Каушал Моди
@kaushalmodi: Оказывается, это electric-pair-modeработает путем подключения post-self-insert-hook, а не путем изменения привязки клавиш.
Ниспио
C-h kговорит вам точно, что происходит для нажатия клавиши. Если вы посмотрите на документацию self-insert-command, там очень четко написано, что post-self-insert-hookона запускается после завершения команды.
Шости
@shosti: в этом простом примере да. Но что если что, если расширение использует, after-change-functionsкак упоминает Джордон в своем ответе? Документация для функции, вероятно, не будет упоминать этот хук, не так ли?
Ниспио
Извините, я должен был быть более конкретным. C-h k+ стандартные зацепки == полное поведение (более или менее). Конечно, иногда это оставляет много возможностей, но все же гораздо прозрачнее, чем любая другая сложная программная система, о которой я знаю.
Шости

Ответы:

13

Нет простого способа точно узнать, что будет делать нажатие одной клавиши.

Если вы видите дополнительное поведение, всегда проверяйте общие хуки. См. Список здесь: http://www.gnu.org/software/emacs/manual/html_node/elisp/Standard-Hooks.html.

В большинстве случаев важными являются:

  • после изменения-функций
  • перед тем с изменением функций
  • первый переключающий крюк
  • после командно-крюк
  • предварительно командный крючок
  • после самостоятельной вставки крюка

Вам нужно будет проверить эти хуки и посмотреть, какие функции они содержат, чтобы определить, какой из них изменяет ваше поведение.

Если функции в этих хуках не полностью описывают наблюдаемое поведение, обратитесь к функциям за советом, который появится в их документации от describe-function.


Редактировать: я написал несколько функций, чтобы помочь описать ловушку лучше, чем проходить функции по очереди: https://gist.github.com/jordonbiondo/bad03e44bb053db0f1eb Вы можете использовать describe-hookопределенные здесь, как и другие функции описания. Вот пример его вывода:

И вот весь код на случай, если суть исчезнет:

(defun guess-all-hooks ()
  "Return a list of all variables that are probably hook lists."
  (let ((syms '()))
    (mapatoms
     (lambda (sym)
       (if (ignore-errors (symbol-value sym))
           (let ((name (symbol-name sym)))
             (when (string-match "-\\(hook[s]?\\|functions\\)$" name)
               (push sym syms))))))
    syms))

(defun face-it (str face)
  "Apply FACE to STR and return."
  (propertize str 'face face))

(defun describe-hook (hook)
  "Display documentation about a hook variable and the
functions it contains."
  (interactive
   (list (completing-read
          "Hook: " (mapcar (lambda (x) (cons x nil)) (guess-all-hooks)))))
  (let* ((sym (intern hook))
         (sym-doc (documentation-property sym 'variable-documentation))
         (hook-docs (mapcar
                     (lambda (func)
                       (cons func (ignore-errors (documentation func))))
                     (symbol-value sym))))
    (switch-to-buffer
     (with-current-buffer (get-buffer-create "*describe-hook*")
       (let ((inhibit-read-only t))
         (delete-region (point-min) (point-max))
         (insert (face-it "Hook: " 'font-lock-constant-face) "\n\n")
         (insert (face-it (concat "`" hook "'") 'font-lock-variable-name-face))
         (replace-string "\n" "\n\t" nil
                         (point)
                         (save-excursion
                           (insert "\n" sym-doc "\n\n")
                           (1- (point))))
         (goto-char (point-max))
         (insert (face-it "Hook Functions: " 'font-lock-constant-face) "\n\n")
         (dolist (hd hook-docs)
           (insert (face-it (concat "`" (symbol-name (car hd)) "'")
                            'font-lock-function-name-face)
                   ": \n\t")
           (replace-string "\n" "\n\t" nil
                           (point)
                           (save-excursion
                             (insert (or (cdr hd) "No Documentation") "\n\n")
                             (1- (point))))
           (goto-char (point-max))))
       (help-mode)
       (help-make-xrefs)
       (read-only-mode t)
       (setq truncate-lines nil)
       (current-buffer)))))
Джордон Биондо
источник
Означает ли это, что когда функция получает рекомендации, документация автоматически обновляется с учетом изменений?
Ниспио
Я не знаю, обновляются ли фактические свойства, но возвращаемое значение documentationобновляется для отражения.
Джордон Биондо
1
@nispio да, это так.
Малабарба
1
Код / функция в gist.github.com/jordonbiondo/bad03e44bb053db0f1eb может и, на мой взгляд, должен быть включен в ответ. Я думаю, что SE ответ имеет ограничение в 30000 символов.
Фахим Митха
4

Возможно, не полный ответ на ваш вопрос, но пакет helm-descbindsпомогает вам искать все определенные привязки клавиатуры из представления ярлыка ascii. Для каждого удара, он показывает вам интерактивную функцию , связанную с клавиши быстрого доступа, и вы можете попросить , helm-descbindsчтобы описать его, или выполнить его непосредственно из результатов поиска.

введите описание изображения здесь

Вот описание пакета с сайта GitHub:

Helm Descbinds предоставляет интерфейс для описаний-привязок в emacs, что делает в настоящее время активные привязки клавиш интерактивными для поиска с помощью helm.

Дополнительно у вас есть следующие действия

  • Выполнить команду
  • Опишите команду
  • Найти команду

И C-zдаст вам постоянное описание текущей команды.

Амелио Васкес-Рейна
источник
2
Это круто. Я определенно связать это C-h b. Мое единственное желание, чтобы я мог перейти к элементу в списке, введя фактическую последовательность клавиш вместо того, чтобы набиратьC - c _ C - p
nispio