Как связать ключ с «функцией, представленной следующей последовательностью клавиш»? - PullRequest
8 голосов
/ 27 декабря 2010

Я только начинаю изучать emacs (woohoo!), И я довольно счастливо слоняюсь по своему .emacs. К сожалению, я еще не знаю Lisp, поэтому у меня проблемы с основами.

Я уже переназначил несколько клавиш, пока не исправил свою мышечную память:

(global-set-key (kbd "<f9>") 'recompile)

Хорошо. Но как я могу сказать ключу «имитировать нажатие нескольких клавиш»? Например, я не знаю, заставить <f1> сделать то же самое, что и C-u 2 C-x } (расширить буфер двумя символами).

Один из способов - найти, что C-x } вызывает shrink-window-horizontally, и сделать что-то лямбда-выражение. Это, конечно, аккуратный и элегантный способ (как ты это делаешь?). Но наверняка есть способ определить <f1> для отправки нажатий клавиш C-u 2 C-x }?

Ответы [ 4 ]

18 голосов
/ 27 декабря 2010

Конечно, есть, и это очевидный путь:

(global-set-key (kbd "<f1>") (kbd "C-u 2 C-x }"))
8 голосов
/ 27 декабря 2010

Для всего долгосрочного, я бы порекомендовал подход, показанный seh, поскольку он, естественно, будет более устойчивым в большинстве ситуаций. Конечно, это требует немного больше работы и ноу-хау, но все это стоит того:)

Подход

angus похож на урезанную версию функции макросов клавиатуры, которая дает Emacs свое имя (и немного проще в использовании, чем макросы для рассматриваемого примера). Однако вы определенно должны знать о макросах - они могут быть чрезвычайно полезны, и для чего-то более сложного быстро становится гораздо проще динамически записать один из них, чем выписывать все отдельные ключи вручную.

Вот краткое изложение, которое я сам написал о самых важных битах:

;;;; * Keyboard macros
;;   C-x (          or F3  Begin recording.
;;                     F3  Insert counter (if recording has already commenced).
;;   C-u <n> C-x (  or F3  Begin recording with an initial counter value <n>.
;;   C-x )          or F4  End recording.
;;   C-u <n> C-x )  or F4  End recording, then execute the macro <n>-1 times.
;;   C-x e          or F4  Execute the last recorded keyboard macro.
;;       e          or F4  Additional e or F4 presses repeat the macro.
;;   C-u <n> C-x e  or F4  Execute the last recorded keyboard macro <n> times.
;;   C-x C-k r             Apply the last macro to each line of the region.
;;   C-x C-k e             Edit a keyboard macro (RET for most recent).
;;   C-x C-k b             Set a key-binding.
;;
;; If you find yourself using lots of macros, you can even name them
;; for later use, and save them to your init file.
;;   M-x name-last-kbd-macro RET (name) RET
;;   M-x insert-kbd-macro RET (name) RET
;;
;; For more documentation:
;;   C-h k C-x (
;;   M-: (info "(emacs) Keyboard Macros") RET

Если мы поиграем с примером из вопроса, вы увидите, как некоторые из этих вещей связаны друг с другом ...

Для начала вы можете определить макрос с помощью F3 Cu 2 Cx } F4

Затем вы можете временно связать его с F1 с помощью Cx Ck b F1 (на самом деле это не так Значение true, если F1 в настоящее время является префиксным ключом для существующей таблицы ключей, поскольку при его интерактивном наборе просто будет запрошен остаток. Вы можете обойти это в коде с помощью (global-set-key (kbd "<f1>") ...), но я бы предложил придерживаться зарезервированных привязок ).

Если вы затем используете describe-key ( Ch k ) для проверки того, что связано с этим ключом, Emacs покажет вам выражение (lambda), которое вы можете скопировать в свой файл инициализации, если вы этого хотите.

Кроме того, вы можете назвать макрос и попросить Emacs вставить код в текущий буфер:

М-х name-last-kbd-macro RET (имя) RET
М-х insert-kbd-macro RET RET

Этот код будет выглядеть иначе, чем лямбда-выражение, показанное describe-key, но если вы оцените вставленный макрос, вы увидите эквивалентность. Вы также можете показать, что выражение (kbd "...") также имеет одно и то же значение, и, следовательно, это всего лишь альтернативные способы сделать то же самое.

(Вы можете использовать буфер * scratch * для оценки кода, перемещая точку после конца выражения и набирая Cx Ce , чтобы показать значение в минибуфере или Cj для вставки значения в буфер).

Обратите внимание, что для вставленного кода используется fset, чтобы назначить макрос для символа. Вы можете привязать макрос к клавише, либо выполнив (fset), а затем присвоив этот символ клавише с (global-set-key), либо вы можете игнорировать (fset) и просто напрямую назначить значение макроса. Это, конечно, прямо эквивалентно ответу Ангуса.

Редактировать: Я только что заметил, что есть kmacro-name-last-macro функция, связанная с Cx Ck n , которая по форме почти идентична name-last-kbd-macro , но который генерирует форму лямбда-выражения, видимую при использовании kmacro-bind-to-key ( Cx Ck b ) и describe-key.

8 голосов
/ 27 декабря 2010

Я буду использовать shrink-window-horizontally в качестве примера функции, но вы можете обобщить идею для любых привязок, которые вы хотите определить.

Если вы хотите использовать два в качестве величины по умолчанию, чтобы уменьшить окно, а не один, попробуйте следующее:

(global-set-key [f9]
  (lambda (&optional n)
    (interactive "P")
    (shrink-window-horizontally (or n 2))))

Это связывает клавишу F9 с интерактивной функцией, принимающей аргумент префикса . Если вы просто нажмете F9 , , вы не передадите аргумент , который вызывает значение по умолчанию 2, поскольку параметр n получит nil в качестве аргумента. Однако, если вы нажмете, скажем, C-u 10 F9 , вы передадите десять в качестве аргумента для n. Это позволяет более гибко использовать привязку.

0 голосов
/ 27 марта 2018

general-simulate-key из general.el работает лучше (в моем случае последовательность с всплывающими окнами и меняющимися раскладками клавиш, которые я не смог получить при работе с макросами): https://github.com/noctuid/general.el#simulating-keypresses

...