23.17 Сканирование клавиатурных карт

В этом разделе описаны функции, используемые для сканирования всех текущих клавиатурных карт с целью вывода справочной информации. Для отображения привязок в конкретной клавиатурной карте можно использовать команду describe-keymap (см. Другие команды справки в Руководстве GNU Emacs)

Функция: accessible-keymaps keymap &optional prefix

Эта функция возвращает список всех клавиатурных карт, достижимых (через ноль или более префиксных клавиш) из keymap. Возвращаемое значение — это ассоциационный список с элементами вида (key . map), где key — это префиксная клавиша, определение которой в keymap равно map.

Элементы ассоциационного списка упорядочены так, что key возрастает по длине. Первый элемент всегда — ([] . keymap), поскольку указанная клавиатурная карта доступна из самой себя с префиксом без событий.

Если задан prefix, это должна быть префиксная последовательность клавиш; тогда accessible-keymaps включает только те подкарты, чьи префиксы начинаются с prefix. Эти элементы выглядят так же, как и в значении (accessible-keymaps); единственное отличие в том, что некоторые элементы опущены.

В примере ниже возвращённый ассоциационный список показывает, что клавиша ESC, отображаемая как ‘^[’, является префиксной клавишей, чьё определение — разрежённая клавиатурная карта (keymap (83 . center-paragraph) (115 . foo)).

(accessible-keymaps (current-local-map))
⇒(([] keymap
      (27 keymap   ; Обратите внимание, эта клавиатурная карта для ESC повторяется ниже.
          (83 . center-paragraph)
          (115 . center-line))
      (9 . tab-to-tab-stop))

   ("^[" keymap
    (83 . center-paragraph)
    (115 . foo)))

В следующем примере C-h — это префиксная клавиша, использующая разрежённую клавиатурную карту, начинающуюся с (keymap (118 . describe-variable)…). Другой префикс, C-x 4, использует клавиатурную карту, которая также является значением переменной ctl-x-4-map. Событие mode-line — одно из нескольких фиктивных событий, используемых как префиксы для действий мыши в специальных частях окна.

(accessible-keymaps (current-global-map))
⇒ (([] keymap [set-mark-command beginning-of-line …
                   delete-backward-char])
    ("^H" keymap (118 . describe-variable) …
     (8 . help-for-help))
    ("^X" keymap [x-flush-mouse-queue …
     backward-kill-sentence])
    ("^[" keymap [mark-sexp backward-sexp …
     backward-kill-word])
    ("^X4" keymap (15 . display-buffer) …)
    ([mode-line] keymap
     (S-mouse-2 . mouse-split-window-horizontally) …))

Это не все клавиатурные карты, которые вы могли бы увидеть в действительности.

Функция: map-keymap function keymap

Функция map-keymap вызывает function один раз для каждой привязки в keymap. Она передаёт два аргумента: тип события и значение привязки. Если у keymap есть родитель, привязки родителя также включаются. Это работает рекурсивно: если родитель сам имеет родителя, то привязки дедушки также включаются и так далее.

Эта функция — самый чистый способ просмотра всех привязок в клавиатурной карте.

Функция: where-is-internal command &optional keymap firstonly noindirect no-remap

Эта функция является вспомогательной подпрограммой для команды where-is (см. Справка в Руководстве GNU Emacs). Она возвращает список всех последовательностей клавиш (любой длины), которые привязаны к command в наборе клавиатурных карт.

Аргумент command может быть любым объектом; он сравнивается со всеми записями клавиатурной карты с помощью eq.

Если keymap равен nil, то используются текущие активные клавиатурные карты, без учёта overriding-local-map (то есть в предположении, что его значение равно nil). Если keymap — это клавиатурная карта, то искомыми картами являются keymap и глобальная клавиатурная карта. Если keymap — это список клавиатурных карт, ищутся только эти клавиатурные карты.

Обычно лучше всего использовать overriding-local-map в качестве выражения для keymap. Тогда where-is-internal ищет именно те клавиатурные карты, которые активны. Чтобы искать только в глобальной карте, передайте значение (keymap) (пустую клавиатурную карту) в качестве keymap.

Если firstonly равен non-ascii, то возвращается один вектор, представляющий первую найденную последовательность клавиш, а не список всех возможных последовательностей. Если firstonly равен t, то возвращается первая последовательность клавиш, но при этом последовательности, состоящие исключительно из ASCII-символов (или мета-вариантов ASCII-символов), имеют приоритет над всеми остальными, и возвращаемое значение никогда не может быть привязкой меню.

Если noindirect не равен nil, where-is-internal не заглядывает внутрь пунктов меню для поиска их команд. Это позволяет искать сам пункт меню.

Пятый аргумент, no-remap, определяет, как эта функция обрабатывает переопределения команд (см. Переопределение команд). Здесь есть два интересных случая:

Если команда other-command переопределена на command:

Если no-remap равен nil, найдите привязки для other-command и считайте их также привязками для command. Если no-remap не равен nil, включите вектор [remap other-command] в список возможных последовательностей клавиш вместо поиска этих привязок.

Если command переопределена на other-command:

Если no-remap равен nil, верните привязки для other-command, а не для command. Если no-remap не равен nil, верните привязки для command, игнорируя тот факт, что она переопределена.

Если команда сопоставлена с привязкой клавиш, такой как [some-event], и some-event имеет в списке свойств символа ненулевое свойство non-key-event, то эта привязка игнорируется where-is-internal.

Команда: describe-bindings &optional prefix buffer-or-name

Эта функция создаёт список всех текущих привязок клавиш и отображает его в буфере с именем *Help*. Текст сгруппирован по режимам — сначала второстепенные режимы, затем основной режим, затем глобальные привязки.

Если prefix не равен nil, это должна быть префиксная клавиша; тогда список включает только клавиши, начинающиеся с prefix.

Когда несколько символов с последовательными ASCII-кодами имеют одинаковое определение, они показываются вместе как ‘firstchar..lastchar’. В этом случае вам нужно знать ASCII-коды, чтобы понять, какие символы имеются в виду. Например, в глобальной карте по умолчанию символы ‘SPC .. ~’ описаны одной строкой. SPC — это ASCII 32, ~ — это ASCII 126, а символы между ними включают все обычные печатаемые символы (например, буквы, цифры, знаки препинания и т. д.); все эти символы привязаны к self-insert-command.

Если buffer-or-name не равен nil, это должен быть буфер или имя буфера. Тогда describe-bindings выводит привязки этого буфера, а не текущего.