Ответ 1
Короткий ответ
Проблемная строка:
'(((kbd "<kp-1>") . "a"))
Решение (принудительное вычисление макроса):
;; Single quote changed to back-quote and added a comma
`((,(kbd "<kp-1>") . "a"))
Длинный ответ
Макрос define-minor-mode позволяет создавать незначительные режимы относительно легко (насколько Emacs).
Сначала я покажу, как это делается, тогда я объясню, как это работает:
В общем виде:
(define-minor-mode NAME-mode
"DOCUMENTATION"
INIT-VALUE
"LIGHTER"
;; keymap
'(
(KEY-SEQUENCE . DEFINITION)
(KEY-SEQUENCE . DEFINITION)
... ETC ...
)
;; other options
:KEYWORD-ARG VALUE
:KEYWORD-ARG VALUE
... ETC ...
)
Конкретный пример с принудительной оценкой макросов в alist:
;; Custom Minor Mode
(define-minor-mode custom-mode
"Doc description, yada yada yada."
;; The initial value - Set to 1 to enable by default
nil
;; The indicator for the mode line.
" CustomMode"
;; The minor mode keymap
`(
(,(kbd "C-c C-a") . some-command)
(,(kbd "C-c C-b") . other-command)
("\C-c\C-c" . "This works too")
)
;; Make mode global rather than buffer local
:global 1
)
Альтернативный способ, если вы хотите использовать переменную для раскладки клавиатуры, - это определить переменную keymap и ключевую карту до в описании вспомогательного режима примерно так:
(defvar custom-mode-keymap (make-keymap) "num-mode keymap.")
(define-key custom-mode-keymap (kbd "C-c C-a") 'some-command)
И затем, в определении вашего младшего режима, просто перечислите имя переменной для вашей раскладки клавиатуры, а не alist
(define-key custom-mode-keymap (kbd "C-c C-b") 'other-command)
;; Num pad enable
(define-minor-mode custom-mode
...
;; The minor mode bindings.
custom-mode-keymap
Как все работает
Сверху вниз, сразу после define-minor-mode, мы определяем имя команды для переключения второстепенного режима. custom-mode
в этом случае (M-x custom-mode
для переключения режима). Это также определяет переменную с тем же именем.
Сразу после имени команды мы перечислим строку документации для второстепенного режима в кавычках. Это может быть в значительной степени до тех пор, пока вы хотите.
Далее у нас есть несколько вариантов. Самый простой выбор - просто перечислить три вещи, а затем любые дополнительные параметры. Три вещи должны быть перечислены в следующем порядке. Эти три вещи:
-
Значение инициализации для переменной второстепенного режима.
nil
будет отключен по умолчанию. Для чего-то другого, кромеnil
, оно будет включено по умолчанию. -
Зажигалка. Зажигалка - это просто то, что отображается в строке режима внизу, когда включен второстепенный режим. Это должно быть кратким, и он часто помогает с точки зрения форматирования запускать его с пробелом.
-
Раскладка клавиатуры. Ключевая карта может быть определена как переменная или алист (список ассоциаций). Поскольку использование alist проще и короче, это то, что я использовал в примере. Алист должен быть в форме
(key-sequence . definition)
.
Если вы определяете ключевую карту как alist, вам нужно следить за некоторыми моментами, особенно если вы привыкли определять глобальные привязки клавиш. Во-первых, имена команд не цитируются. Во-вторых, если вы хотите использовать макрос, , вы должны заставить его оценивать (и на SO). Это делается с комбинацией обратной цитаты (не одинарной кавычки) и запятой. Вы можете увидеть, как это делается в примере с макросом kbd. Я также включил определение нажатия клавиш, если вы не используете макрос kbd. Если вы просто укажете строку в вашей раскладке, она будет распечатана, когда будет нажата определенная комбинация клавиш (точно так же, как для определения привязок глобальных клавиш).
Ключевая карта не будет работать с макросами kbd, если вы не заставляете оценивать макросы kbd с комбинацией обратной цитаты и запятой. Как это:
`((,(kbd "C-c C-a") . some-command))
Наконец, вы можете добавить дополнительные опции, используя keyword-args формы :blah
. В примере я использовал :global
. Мы могли бы определить весь режим с ключевыми словами-args, но короче просто перечислить значение init, lightter и keymap в правильном порядке.