3

I'm trying to define a minor mode that rebinds M-q to a modified version of fill-paragraph. What I've written so far:

(defun myfun ()
  (message "myfun called"))
(define-minor-mode mymode
  "Test for minor mode keymap."
  :lighter " MM"
  :keymap '(([M-q] . myfun)))

doesn't work, as M-q is still bound to fill-paragraph when mymode is active. Can anyone spot the issue with my code and tell me how to rebind that key properly?

2
  • Please move the solution to an answer - remove it from the question. (You can accept your own answer.)
    – Drew
    May 1, 2021 at 14:18
  • @Drew Done, thanks.
    – gosbi
    May 2, 2021 at 6:15

3 Answers 3

2

Contrast M-f1 for a function key with ?\M-f for a character. You've bound myfun to [M-q] which means the one-key sequence where the key is the function key called q (which does not exist) with the modifier whose prefix is M (which is meta). Instead of referencing a function key q, you need to reference the character q. You can write this [?\M-q], or in string notation "?\M-q". You can also use the ESC prefix (written \e as a character) instead of the meta modifier: "\eq" or [?\e \q].

(Do not use [escape q], because that would override the default redirection of the escape function key to the escape character ?\e, and so pressing Escape key would no longer be equivalent to Meta+key.)

1
  • Thanks a lot, I changed [M-q] to [?\M-q], and now the function the rebound keys work. There was another problem (the key must be bound to a command, not a function), but that was easier to fix. Will update the question and add the working version.
    – gosbi
    May 1, 2021 at 11:40
1

I'd consider calling (define-key mymode-map [remap fill-paragraph] #'myfun) from mymode-hook rather than defining it in the minor mode.

(defun remap-fill-paragraph ()
  (define-key mymode-map [remap fill-paragraph] #'myfun))

(add-hook 'mymode-hook #'remap-fill-paragraph)

This means you don't have to remember to change the minor-mode mapping if you ever change the default mapping for fill-paragraph.

Unfortunately (based on a single quick test) it seems that the expansion of the define-minor-mode Lisp macro is not smart enough to handle a [remap ...] within the :keymap form, hence the need to use the more verbose approach.

0

There are two problems in the code above:

  1. The code was bound to the non-existing q function key (see Gilles' answer).
  2. In order to be added to a keymap, functions must be commands (i.e. interactive).

The following code works and solves both problems:

(defun myfun ()
  (interactive)
  (message "myfun called"))
(define-minor-mode mymode
  "Test for minor mode keymap."
  :lighter " MM"
  :keymap '([?\M-q] . myfun))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.