Как создать привязки для пользовательского второстепенного режима в Emacs

Вопрос:

Как создать пользовательские привязки клавиш для второстепенных режимов? Что-то вроде этого.

Вот что я до сих пор. Я пытаюсь получить только один пользовательский ключ для работы:

(define-minor-mode num-mode
       "Toggle the Num pad keys.
     With no argument, this command toggles the mode.
     Non-null prefix argument turns on the mode.
     Null prefix argument turns off the mode.

     When Num mode is enabled, the num pad inserts the
     keys you see on the pad. This may over ried existing
     definitions, and is probably only usefule if you aref
     running Emacs through a terminal."
      ;; The initial value.
      nil
      ;; The indicator for the mode line.
      " NumPad"
      ;; The minor mode bindings.
      ;; This doesn't work right now!!!!
       '(((kbd "<kp-1>") . "a"))
      :global 1
)

Когда я нажимаю "1" на цифровой клавиатуре после вызова моего настраиваемого вспомогательного режима, "num-mode" и проверки его включенности в мини-буфере, я получаю сообщение об ошибке <kp-1> is undefined. Я хочу, чтобы текст a был напечатан, где указатель, когда я нажал <kp-1>. (просто тест)

Контекст:

Итак, я обычно использую свой номерной номер для перемещения между буферами (клавиши со стрелками перемещают меня по соответствующим направлениям). Это устанавливается глобально. Я хочу создать второстепенный режим, который я могу вызвать, когда хочу использовать свой номерный блок для простого ввода чисел.

По умолчанию клавишами моей цифровой клавиатуры являются undefined. Я использую <kp-0> - <kp-9> для определения привязок клавиш для клавиш numpad.

Я могу создать второстепенный режим, который я могу вызвать, но я не могу прикрепить никаких привязок. Это справедливо для всех привязок клавиш, в том числе к тому, что не указано нигде.

Спасибо за любую помощь!

Ответ 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 в правильном порядке.

Ответ 2

В определении вашего младшего режима должен быть такой код:

(defvar your-mode-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map parent-mode-shared-map)
    (define-key map "\C-c\C-a" 'some-defun)
    (define-key map "\C-c\C-b" 'some-other-sexp)
    map)

(use-local-map your-mode-map)

Вы можете посмотреть многие режимы, доступные в EmacsWiki для справки.

Ответ 3

Посмотрите на это (только для информации о привязках клавиш):

http://www.gnu.org/software/emacs/manual/html_node/emacs/Key-Bindings.html#Key-Bindings

http://www.gnu.org/software/emacs/manual/html_node/emacs/Local-Keymaps.html#Local-Keymaps

Из http://xahlee.org/emacs/reclaim_keybindings.html:

Хорошо написанные основные режимы будут запущены в конце. Таким образом, вы можете использовать крючок для определения привязки клавиш. Незначительные режимы обычно не имеют крючков. В этом случае вы можете сначала вызвать "(требуется <символ второстепенного режимa > " ), а затем определить привязку клавиш.

Также вы можете посмотреть: http://www.cs.utah.edu/dept/old/texinfo/emacs19/emacs_35.html#SEC347

Возможно, принятый ответ здесь также поможет вам.