Как вы обновляете определение второстепенного режима по мере его разработки?

13

Я начал кодировать второстепенный режим, чтобы обеспечить некоторые сочетания клавиш. Моя первая попытка была опечатка:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(([b] . 'previous-line)))

Я намеревался использовать bключ и сразу понял, что должен был использовать "b"вместо [b]. Поэтому я переопределил второстепенный режим:

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  nil nil
  '(("b" . 'previous-line)))

Однако это не сработало. Это вызвало у меня погоню за диким гусем через различные способы привязки ключей (например, (kbd ...), [...] и т. Д.). Наконец я понял, что простая переоценка (define-minor-mode ...)формы ничего не меняет, я застрял с исходной картой сломанного ключа. Затем я попытался изменить раскладку клавиатуры напрямую, (define-key borked-mode-map ...)но не смог загрузить исправленную раскладку. Наконец я перезапустил Emacs, и мой второстепенный режим был правильно загружен.

Мой вопрос: как вы обновляете определение второстепенного режима по мере его разработки? Есть ли способ очистить сломанное определение, или вам нужно перезапустить emacs, чтобы убрать битые биты?

Тайлер
источник

Ответы:

11

При первой оценке define-minor-modeего он определяет переменную borked-mode-mapс указанными вами связями клавиш. Однако, как только этот символ был определен, переоценка define-minor-modeне изменит его.

Вы можете удалить различные borked-mode-xxxсимволы, используя, uninternа затем пересмотреть свой код. Пытаться:

(unintern 'borked-mode-map)

Возможно, вам будет интересно расширить define-minor-modeмакрос, чтобы увидеть, что он на самом деле делает. Поставь точку в конце и позвони M-x pp-macroexpand-last-sexp. Это откроет новый буфер, показывающий развернутый макрос. Там вы увидите defvarвызовы, используемые для настройки переменных режима. Если вы прочитаете справку, defvarвы увидите, что начальное значение используется только в том случае, если определяемый символ является недействительным - если он существует, последующие defvarвызовы не изменят его значение.

glucas
источник
13

Я думаю, что лучший ответ, который я могу вам дать, это держаться подальше от «встроенной функции сочетания клавиш» define-minor-mode. использование

(defvar borked-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [b] 'previous-line)
    ...
    map))

(define-minor-mode borked-mode
  "A mode defined with a broken key binding"
  :global nil
  ...)

Вместо. Затем вы можете использовать C-M-xдля переоценки этих определений.

Стефан
источник
1
defvarне буду оценивать это значение снова после C-M-x:) Вам нужно defparameterили отдельно setf.
wvxvw
Как указывает @wvxvw, это фактически не решает проблему. Ваш пример кода делает то же самое, что и define-minor-modeмакрос: вызов defvarдля определения карты. Оценка этого defvar во второй раз не имеет никакого эффекта.
glucas
7
@wvxvw Если вы используете C-M-x( eval-defun) для переоценки, defvarто переменная будет обновлена. Это особый случай в eval-defun; если вы позвоните eval-bufferили eval-regionтогда существующее значение не изменится.
Жиль "ТАК ... перестать быть злым"
Ах, это похоже на ключевой момент.
glucas
1
Обратите внимание, что C-M-xв defvarформе обновляется только сама переменная mode-map. Вы также должны C-M-xв define-minor-modeформе перевести измененную карту в «второстепенный режим». Я пытался выяснить, почему, расширяя макросы, но это вне меня.
Тайлер